diff --git a/common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkConfig.kt b/common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkConfig.kt index 07814181d..9b17458d7 100644 --- a/common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkConfig.kt +++ b/common/src/main/kotlin/org/valkyrienskies/clockwork/ClockworkConfig.kt @@ -100,6 +100,9 @@ object ClockworkConfig { @ConfigEntry(description = "The maximum surface area (in blocks) that the hot air balloon floodfill will scan when trying to determine the balloon's exterior.", min = 1.0) var hotAirBalloonMaxScanSurface = 100000.0 + @ConfigEntry(description = "Display invalid non-air blocks when doing a hot air balloon floodfill.") + var hotAirBalloonDebugInvalidBlocks = false + @ConfigEntry(description = "Force multiplier when no rpm is given") var angleFollowingBaseAngleErrorMultiplier = 50.0 diff --git a/common/src/main/kotlin/org/valkyrienskies/clockwork/content/forces/BalloonController.kt b/common/src/main/kotlin/org/valkyrienskies/clockwork/content/forces/BalloonController.kt index d11572e4e..3488e6657 100644 --- a/common/src/main/kotlin/org/valkyrienskies/clockwork/content/forces/BalloonController.kt +++ b/common/src/main/kotlin/org/valkyrienskies/clockwork/content/forces/BalloonController.kt @@ -23,6 +23,7 @@ import org.valkyrienskies.clockwork.content.forces.data.BalloonData import org.valkyrienskies.clockwork.content.forces.data.BalloonData.PhysBalloonData import org.valkyrienskies.clockwork.util.AABBHelper.mergeAdjacentFast import org.valkyrienskies.clockwork.util.AerodynamicUtils.dimensionMap +import org.valkyrienskies.clockwork.util.DebugOutputUtil.indicatePositionToNearbyPlayers import org.valkyrienskies.core.api.VsBeta import org.valkyrienskies.core.api.attachment.getAttachment import org.valkyrienskies.core.api.ships.LoadedServerShip @@ -358,7 +359,9 @@ class BalloonController: ShipPhysicsListener { for (dir in Direction.values()) { val n = cur.relative(dir) - if (level.getBlockState(n).isValidBalloonEnclosure(level, n)) continue + val bs = level.getBlockState(n) + if (bs.isValidBalloonEnclosure(level, n)) + continue val nl = n.asLong() if (!visited.contains(nl)) q.add(nl) } @@ -389,12 +392,21 @@ class BalloonController: ShipPhysicsListener { @JvmStatic fun BlockState.isValidBalloonEnclosure(level: Level, pos: BlockPos): Boolean { - return !this.isAir && this.isCollisionShapeFullBlock(level, pos) + if (this.isAir) return false + if (this.isCollisionShapeFullBlock(level, pos)) return true + // For debugging non-trivial failures when building balloon enclosures (non-full blocks) + if (ClockworkConfig.SERVER.hotAirBalloonDebugInvalidBlocks) + indicatePositionToNearbyPlayers(level, pos.center, "debug.invalid_balloon_enclosure", pos) + return false } @JvmStatic fun BlockState.isValidBalloonEnclosureDirectional(level: Level, pos: BlockPos, direction: Direction): Boolean { - return !this.isAir && !this.isFaceSturdy(level, pos, direction.opposite) + if (this.isAir) return false + if (this.isFaceSturdy(level, pos, direction.opposite)) return true + if (ClockworkConfig.SERVER.hotAirBalloonDebugInvalidBlocks) + indicatePositionToNearbyPlayers(level, pos.center, "debug.invalid_balloon_enclosure_directional", direction, pos) + return false } } } diff --git a/common/src/main/kotlin/org/valkyrienskies/clockwork/util/DebugOutputUtil.kt b/common/src/main/kotlin/org/valkyrienskies/clockwork/util/DebugOutputUtil.kt new file mode 100644 index 000000000..f2d384a8c --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/clockwork/util/DebugOutputUtil.kt @@ -0,0 +1,26 @@ +package org.valkyrienskies.clockwork.util + +import net.minecraft.client.multiplayer.ClientLevel +import net.minecraft.core.particles.ParticleTypes +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.Level +import net.minecraft.world.phys.Vec3 +import org.valkyrienskies.clockwork.ClockworkLang + +object DebugOutputUtil { + fun indicatePositionToNearbyPlayers(level: Level, pos: Vec3, langKey: String?, vararg args: Any) { + val particleType = ParticleTypes.END_ROD + val particleCount = 20 + + val player = level.getNearestPlayer(pos.x, pos.y, pos.z, 256.0, false) + if (langKey != null) player?.displayClientMessage(ClockworkLang.translate(langKey, *args).component(), false) + if (level is ServerLevel) + level.sendParticles( + particleType, + pos.x, pos.y, pos.z, + particleCount, 0.3, 0.3, 0.3, 0.0 + ) + else if (level is ClientLevel) + repeat(particleCount) { level.addParticle(particleType, pos.x, pos.y, pos.z, 0.0, 0.0, 0.0) } + } +} \ No newline at end of file diff --git a/common/src/main/resources/assets/vs_clockwork/lang/en_us.json b/common/src/main/resources/assets/vs_clockwork/lang/en_us.json index 76e34b4ba..af8ae2e19 100644 --- a/common/src/main/resources/assets/vs_clockwork/lang/en_us.json +++ b/common/src/main/resources/assets/vs_clockwork/lang/en_us.json @@ -464,5 +464,8 @@ "vs_clockwork.ponder.solid_delivery.text_9": "and belts", "death.attack.gas_burn": "%s was singed to a crisp", - "death.attack.gas_explosion": "%s couldn't handle the pressure" + "death.attack.gas_explosion": "%s couldn't handle the pressure", + + "vs_clockwork.debug.invalid_balloon_enclosure": "Invalid balloon block: %s", + "vs_clockwork.debug.invalid_balloon_enclosure_direction": "Invalid balloon block for direction %s: %s" }