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.server.level.ServerPlayer
|
||||||
import net.minecraft.sounds.SoundEvents
|
import net.minecraft.sounds.SoundEvents
|
||||||
import net.minecraft.sounds.SoundSource
|
import net.minecraft.sounds.SoundSource
|
||||||
|
import net.minecraft.tags.BlockTags
|
||||||
import net.minecraft.world.level.ClipContext
|
import net.minecraft.world.level.ClipContext
|
||||||
import net.minecraft.world.level.block.Block
|
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.HitResult
|
||||||
|
import net.minecraft.world.phys.shapes.BooleanOp
|
||||||
import net.minecraft.world.phys.shapes.CollisionContext
|
import net.minecraft.world.phys.shapes.CollisionContext
|
||||||
|
import net.minecraft.world.phys.shapes.Shapes
|
||||||
import net.minecraftforge.client.event.RenderLevelStageEvent
|
import net.minecraftforge.client.event.RenderLevelStageEvent
|
||||||
import net.minecraftforge.event.entity.living.LivingDeathEvent
|
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.NULLABLE_MINECRAFT_SERVER
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
import ru.dbotthepony.mc.otm.ServerConfig
|
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.MatteryPlayerCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact
|
import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryPlayer
|
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.DynamicBufferSource
|
||||||
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
|
||||||
import ru.dbotthepony.mc.otm.client.render.element
|
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.component3
|
||||||
import ru.dbotthepony.mc.otm.core.formatPower
|
import ru.dbotthepony.mc.otm.core.formatPower
|
||||||
import ru.dbotthepony.mc.otm.core.genericPositions
|
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.plus
|
||||||
import ru.dbotthepony.mc.otm.core.set
|
import ru.dbotthepony.mc.otm.core.set
|
||||||
import ru.dbotthepony.mc.otm.core.shortestDistanceBetween
|
import ru.dbotthepony.mc.otm.core.shortestDistanceBetween
|
||||||
@ -74,23 +74,43 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
|
|||||||
cooldown = nbt.getInt("cooldown")
|
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 {
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val a = ply.level.getBlockState(blockPos)
|
return !isWall(blockPos.below()) && isAirGap(blockPos) && isAirGap(blockPos.above())
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class TraceResult(val pos: BlockPos? = null, val phasedBlocks: Collection<BlockPos> = listOf()) {
|
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
|
return TraceResult.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val testPositions = ply.genericPositions()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
result.direction == Direction.UP &&
|
result.direction == Direction.UP &&
|
||||||
isValidPosition(result.blockPos.above()) &&
|
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())
|
return TraceResult(result.blockPos.above())
|
||||||
}
|
}
|
||||||
|
|
||||||
for (y in 0 .. ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
|
for (y in (if (ply.level.getBlockState(result.blockPos).`is`(BlockTags.CLIMBABLE)) -1 else 0) .. ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) {
|
||||||
val pos = result.blockPos + BlockPos(0, y + 1, 0)
|
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())
|
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
|
return TraceResult.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,6 +271,9 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
|
|||||||
DynamicBufferSource(maximalInitialBufferSize = 256)
|
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 SPRITE = ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/item/black_hole.png").element(0f, 0f, 16f, 16f, 16f, 16f)
|
||||||
|
|
||||||
val POWER_COST_DESCRIPTION =
|
val POWER_COST_DESCRIPTION =
|
||||||
|
Loading…
Reference in New Issue
Block a user