Phase through walls

This commit is contained in:
DBotThePony 2022-10-13 16:36:28 +07:00
parent c3784f8043
commit 5586404512
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -7,6 +7,7 @@ import net.minecraft.ChatFormatting
import net.minecraft.client.renderer.LevelRenderer import net.minecraft.client.renderer.LevelRenderer
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.core.Direction import net.minecraft.core.Direction
import net.minecraft.core.Vec3i
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer 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.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MNames import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger import ru.dbotthepony.mc.otm.triggers.EnderTeleporterFallDeathTrigger
import java.util.LinkedList
import kotlin.math.sin import kotlin.math.sin
class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiveFeature(AndroidFeatures.ENDER_TELEPORTER, capability) { 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<BlockPos>): 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 { private fun trace(): TraceResult {
val headPosition = ply.eyePosition val headPosition = ply.eyePosition
val aimVector = ply.getViewVector(1f) val aimVector = ply.getViewVector(1f)
@ -146,6 +173,30 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
return TraceResult(result.blockPos.above()) return TraceResult(result.blockPos.above())
} }
val candidates = LinkedList<TraceResult>()
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<BlockPos>(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) { 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) 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) { 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... // no valid positions...
if (isAirGap(result.blockPos)) { if (isAirGap(result.blockPos)) {
// try to find ground below... // try to find ground below...
@ -187,7 +258,7 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv
val (blockPos) = trace() val (blockPos) = trace()
blockPos ?: return false blockPos ?: return false
cooldown = ServerConfig.EnderTeleporter.COOLDOWN // cooldown = ServerConfig.EnderTeleporter.COOLDOWN
val server = ply.server val server = ply.server