Greatly enhance ender teleporter position validation

This commit is contained in:
DBotThePony 2022-10-13 15:43:58 +07:00
parent 254faa7a64
commit a76d07ecc2
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -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 =