From 558640451244378243583c3634491b27d2c4072b Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 13 Oct 2022 16:36:28 +0700 Subject: [PATCH] Phase through walls --- .../android/feature/EnderTeleporterFeature.kt | 75 ++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt index 4e0cf3410..6cae8a748 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt @@ -7,6 +7,7 @@ import net.minecraft.ChatFormatting import net.minecraft.client.renderer.LevelRenderer import net.minecraft.core.BlockPos import net.minecraft.core.Direction +import net.minecraft.core.Vec3i import net.minecraft.nbt.CompoundTag import net.minecraft.resources.ResourceLocation import net.minecraft.server.level.ServerPlayer @@ -50,6 +51,7 @@ import ru.dbotthepony.mc.otm.core.times import ru.dbotthepony.mc.otm.registry.AndroidFeatures import ru.dbotthepony.mc.otm.registry.MNames import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger +import java.util.LinkedList import kotlin.math.sin class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiveFeature(AndroidFeatures.ENDER_TELEPORTER, capability) { @@ -120,6 +122,31 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv } } + private fun tryToPhaseThroughWall(blockPos: BlockPos, normal: Vec3i, phasedBlocks: MutableList): TraceResult? { + phasedBlocks.clear() + phasedBlocks.add(blockPos) + + for (extend in 1 .. ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) { + val pos = blockPos + normal * extend + + if (isAirGap(pos)) { + for (y in 0 .. ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE - extend) { + val newPos = BlockPos(pos.x, pos.y - y, pos.z) + + if (isValidPosition(newPos)) { + return TraceResult(newPos, phasedBlocks) + } else { + phasedBlocks.add(newPos) + } + } + } else { + phasedBlocks.add(pos) + } + } + + return null + } + private fun trace(): TraceResult { val headPosition = ply.eyePosition val aimVector = ply.getViewVector(1f) @@ -146,6 +173,30 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv return TraceResult(result.blockPos.above()) } + val candidates = LinkedList() + + if (result.direction != Direction.UP && result.direction != Direction.DOWN && !isAirGap(result.blockPos) && ply.xRot in -15f .. 15f) { + val (vx, vy, vz) = ply.getViewVector(1f) + val nearest = Direction.getNearest(vx, vy, vz) + + if (nearest != Direction.UP && nearest != Direction.DOWN) { + // attempt one + val phasedBlocks = ArrayList(ServerConfig.EnderTeleporter.MAX_PHASE_DISTANCE) + var phaseResult = tryToPhaseThroughWall(result.blockPos, nearest.normal, phasedBlocks) + + if (phaseResult != null) { + candidates.add(phaseResult) + } + + // attempt two + phaseResult = tryToPhaseThroughWall(result.blockPos, result.direction.opposite.normal, phasedBlocks) + + if (phaseResult != null) { + candidates.add(phaseResult) + } + } + } + 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) @@ -155,10 +206,30 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv } 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()) + candidates.add(TraceResult(pos, if (y != 0) ImmutableList(y + 1) { result.blockPos + BlockPos(0, it, 0) } else listOf())) + break } } + if (candidates.isNotEmpty()) { + var candiate = candidates.first + var distance = candiate.pos!!.distSqr(result.blockPos) + + val iterator = candidates.listIterator() + iterator.next() + + for (next in iterator) { + val newDistance = next.pos!!.distSqr(result.blockPos) + + if (newDistance < distance) { + candiate = next + distance = newDistance + } + } + + return candiate + } + // no valid positions... if (isAirGap(result.blockPos)) { // try to find ground below... @@ -187,7 +258,7 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv val (blockPos) = trace() blockPos ?: return false - cooldown = ServerConfig.EnderTeleporter.COOLDOWN + // cooldown = ServerConfig.EnderTeleporter.COOLDOWN val server = ply.server