Greatly enhance ender teleporter position validation
This commit is contained in:
parent
254faa7a64
commit
a76d07ecc2
@ -12,15 +12,15 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.tags.BlockTags
|
||||
import net.minecraft.world.level.ClipContext
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.material.Material
|
||||
import net.minecraft.world.phys.HitResult
|
||||
import net.minecraft.world.phys.shapes.BooleanOp
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraftforge.client.event.RenderLevelStageEvent
|
||||
import net.minecraftforge.event.entity.living.LivingDeathEvent
|
||||
import org.lwjgl.opengl.GL11.GL_ALWAYS
|
||||
import org.lwjgl.opengl.GL11.GL_LESS
|
||||
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.ServerConfig
|
||||
@ -29,7 +29,6 @@ import ru.dbotthepony.mc.otm.android.AndroidResearchManager
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
|
||||
import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact
|
||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
||||
import ru.dbotthepony.mc.otm.client.minecraft
|
||||
import ru.dbotthepony.mc.otm.client.render.DynamicBufferSource
|
||||
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
||||
import ru.dbotthepony.mc.otm.client.render.element
|
||||
@ -42,6 +41,7 @@ import ru.dbotthepony.mc.otm.core.component2
|
||||
import ru.dbotthepony.mc.otm.core.component3
|
||||
import ru.dbotthepony.mc.otm.core.formatPower
|
||||
import ru.dbotthepony.mc.otm.core.genericPositions
|
||||
import ru.dbotthepony.mc.otm.core.minus
|
||||
import ru.dbotthepony.mc.otm.core.plus
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.core.shortestDistanceBetween
|
||||
@ -74,23 +74,43 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
|
||||
cooldown = nbt.getInt("cooldown")
|
||||
}
|
||||
|
||||
private fun isValidGround(blockPos: BlockPos): Boolean {
|
||||
return canSupportPlayer(blockPos) && !isWall(blockPos)
|
||||
}
|
||||
|
||||
private fun canSupportPlayer(blockPos: BlockPos): Boolean {
|
||||
val state = ply.level.getBlockState(blockPos)
|
||||
|
||||
if (state.`is`(BlockTags.CLIMBABLE)) {
|
||||
return true // ladders can always support player
|
||||
}
|
||||
|
||||
val shape = state.getCollisionShape(ply.level, blockPos, CollisionContext.of(ply))
|
||||
return Shapes.joinIsNotEmpty(shape, SHAPE_CHECK_SUPPORT_PLAYER, BooleanOp.AND)
|
||||
}
|
||||
|
||||
private fun isWall(blockPos: BlockPos): Boolean {
|
||||
val shape = ply.level.getBlockState(blockPos).getCollisionShape(ply.level, blockPos, CollisionContext.of(ply))
|
||||
return Shapes.joinIsNotEmpty(shape, SHAPE_CHECK_NOT_FENCE, BooleanOp.AND)
|
||||
}
|
||||
|
||||
private fun isAirGap(blockPos: BlockPos): Boolean {
|
||||
val state = ply.level.getBlockState(blockPos)
|
||||
|
||||
if (state.isAir) {
|
||||
return true
|
||||
}
|
||||
|
||||
val shape = state.getCollisionShape(ply.level, blockPos, CollisionContext.of(ply))
|
||||
return shape.isEmpty || !Shapes.joinIsNotEmpty(shape, SHAPE_CHECK_SUPPORT_PLAYER, BooleanOp.AND)
|
||||
}
|
||||
|
||||
private fun isValidPosition(blockPos: BlockPos): Boolean {
|
||||
if (!Block.canSupportCenter(ply.level, blockPos.below(), Direction.UP) && !Block.canSupportRigidBlock(ply.level, blockPos.below()) && ply.level.getBlockState(blockPos.below()).material != Material.LEAVES) {
|
||||
if (!canSupportPlayer(blockPos.below()) && !isWall(blockPos.below().below())) {
|
||||
return false
|
||||
}
|
||||
|
||||
val a = ply.level.getBlockState(blockPos)
|
||||
val b = ply.level.getBlockState(blockPos.above())
|
||||
|
||||
if (a.isAir && b.isAir) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (a.getCollisionShape(ply.level, blockPos).isEmpty && b.getCollisionShape(ply.level, blockPos, CollisionContext.of(ply)).isEmpty) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return !isWall(blockPos.below()) && isAirGap(blockPos) && isAirGap(blockPos.above())
|
||||
}
|
||||
|
||||
private data class TraceResult(val pos: BlockPos? = null, val phasedBlocks: Collection<BlockPos> = listOf()) {
|
||||
@ -115,22 +135,36 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
|
||||
return TraceResult.EMPTY
|
||||
}
|
||||
|
||||
val testPositions = ply.genericPositions()
|
||||
|
||||
if (
|
||||
result.direction == Direction.UP &&
|
||||
isValidPosition(result.blockPos.above()) &&
|
||||
shortestDistanceBetween(ply.genericPositions(), result.blockPos.above().asVector()) <= ServerConfig.EnderTeleporter.MAX_DISTANCE
|
||||
shortestDistanceBetween(testPositions, result.blockPos.above().asVector()) <= ServerConfig.EnderTeleporter.MAX_DISTANCE
|
||||
) {
|
||||
return TraceResult(result.blockPos.above())
|
||||
}
|
||||
|
||||
for (y in 0 .. ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
|
||||
val pos = result.blockPos + BlockPos(0, y + 1, 0)
|
||||
for (y in (if (ply.level.getBlockState(result.blockPos).`is`(BlockTags.CLIMBABLE)) -1 else 0) .. ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
|
||||
val pos = BlockPos(result.blockPos.x, result.blockPos.y + y + 1, result.blockPos.z)
|
||||
|
||||
if (isValidPosition(pos) && shortestDistanceBetween(ply.genericPositions(), pos.asVector()) <= ServerConfig.EnderTeleporter.MAX_DISTANCE) {
|
||||
if (isValidPosition(pos) && shortestDistanceBetween(testPositions, pos.asVector()) <= ServerConfig.EnderTeleporter.MAX_DISTANCE) {
|
||||
return TraceResult(pos, if (y != 0) ImmutableList(y + 1) { result.blockPos + BlockPos(0, it, 0) } else listOf())
|
||||
}
|
||||
}
|
||||
|
||||
// no valid positions...
|
||||
if (isAirGap(result.blockPos)) {
|
||||
// try to find ground below...
|
||||
for (y in 0 downTo -ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
|
||||
val pos = BlockPos(result.blockPos.x, result.blockPos.y + y, result.blockPos.z)
|
||||
|
||||
if (isValidPosition(pos) && shortestDistanceBetween(testPositions, pos.asVector()) <= ServerConfig.EnderTeleporter.MAX_DISTANCE) {
|
||||
return TraceResult(pos, if (y != 0) ImmutableList(-y + 1) { result.blockPos - BlockPos(0, it, 0) } else listOf())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TraceResult.EMPTY
|
||||
}
|
||||
|
||||
@ -237,6 +271,9 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
|
||||
DynamicBufferSource(maximalInitialBufferSize = 256)
|
||||
}
|
||||
|
||||
private val SHAPE_CHECK_NOT_FENCE = Block.box(6.0, 17.0, 6.0, 10.0, 31.0, 10.0)
|
||||
private val SHAPE_CHECK_SUPPORT_PLAYER = Block.box(6.0, 0.0, 6.0, 10.0, 16.0, 10.0)
|
||||
|
||||
val SPRITE = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/item/black_hole.png").element(0f, 0f, 16f, 16f, 16f, 16f)
|
||||
|
||||
val POWER_COST_DESCRIPTION =
|
||||
|
Loading…
Reference in New Issue
Block a user