From 700c5c3420549c5517bf50cbc500f2d909ca5425 Mon Sep 17 00:00:00 2001 From: Adubbz Date: Sat, 6 Jan 2024 21:31:53 +1100 Subject: [PATCH] Refactor temperature filling. Closes #789 and #713 --- .../client/handler/LevelRenderHandler.java | 10 +- .../config/TemperatureConfig.java | 2 +- .../toughasnails/temperature/AreaFill.java | 128 +++++++++++------- .../temperature/TemperatureHelperImpl.java | 2 +- 4 files changed, 89 insertions(+), 53 deletions(-) diff --git a/common/src/main/java/toughasnails/client/handler/LevelRenderHandler.java b/common/src/main/java/toughasnails/client/handler/LevelRenderHandler.java index dc8e3d59..fbc0633b 100644 --- a/common/src/main/java/toughasnails/client/handler/LevelRenderHandler.java +++ b/common/src/main/java/toughasnails/client/handler/LevelRenderHandler.java @@ -57,12 +57,14 @@ private static Set getConnectedBlocks(Player player) { Level level = player.level(); - if (connectedBlocks.isEmpty() || level.getGameTime() % 20L == 0L) - { + // The optimisation is good enough for me, and this isn't really a feature for a broad audience + // If that changes though, the below code is an option. + //if (connectedBlocks.isEmpty() || level.getGameTime() % 20L == 0L) + //{ // Clear old connectedBlocks connectedBlocks.clear(); populateConnectedBlocksForPlayer(player); - } + //} return connectedBlocks; } @@ -78,7 +80,7 @@ private static void populateConnectedBlocksForPlayer(Player player) Set renderPositions = new HashSet<>(); AreaFill.fill(level, playerPos, (checkerLevel, checkedPos) -> { - renderPositions.add(checkedPos); + renderPositions.add(checkedPos.pos()); }); // TODO: This could probably be optimised so that blocks opposite each other can set each other's faces, but this is good enough for now diff --git a/common/src/main/java/toughasnails/config/TemperatureConfig.java b/common/src/main/java/toughasnails/config/TemperatureConfig.java index afb4b858..2177c7f6 100644 --- a/common/src/main/java/toughasnails/config/TemperatureConfig.java +++ b/common/src/main/java/toughasnails/config/TemperatureConfig.java @@ -89,7 +89,7 @@ public void load() environmentalModifierAltitude = addNumber("altitude.environmental_modifier_altitude", 50, -64, 256, "Y level above which environmental modifiers are applied"); // Blocks options - nearHeatCoolProximity = addNumber("blocks.near_heat_cool_proximity", 7, 1, 16, "The proximity which constitutes near a heat or cool source"); + nearHeatCoolProximity = addNumber("blocks.near_heat_cool_proximity", 8, 1, 16, "The proximity which constitutes near a heat or cool source"); // Immersion options onFireTemperatureChange = addNumber("immersion.on_fire_temperature_change", 2, -4, 4, "Amount to change the temperature by when on fire."); diff --git a/common/src/main/java/toughasnails/temperature/AreaFill.java b/common/src/main/java/toughasnails/temperature/AreaFill.java index e897ab5b..55217572 100644 --- a/common/src/main/java/toughasnails/temperature/AreaFill.java +++ b/common/src/main/java/toughasnails/temperature/AreaFill.java @@ -7,6 +7,7 @@ import com.google.common.collect.Sets; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.BoundingBox; import toughasnails.init.ModConfig; @@ -16,49 +17,55 @@ public class AreaFill { - private static final int PROXIMITY_RADIUS = ModConfig.temperature.nearHeatCoolProximity; - public static void fill(Level level, BlockPos pos, PositionChecker checker) { - Set checked = Sets.newHashSet(); - Queue queue = new LinkedList(); - BoundingBox bounds = new BoundingBox(pos.getX() - PROXIMITY_RADIUS, pos.getY() - PROXIMITY_RADIUS, pos.getZ() - PROXIMITY_RADIUS, pos.getX() + PROXIMITY_RADIUS, pos.getY() + PROXIMITY_RADIUS, pos.getZ() + PROXIMITY_RADIUS); + Set checked = Sets.newHashSet(); + Queue queue = new LinkedList(); + + final int maxDepth = ModConfig.temperature.nearHeatCoolProximity; - queue.add(pos); + queue.add(new PosAndDepth(pos, 1)); while (!queue.isEmpty()) { - BlockPos posToCheck = queue.poll(); + PosAndDepth posToCheck = queue.poll(); // Skip already checked positions if (checked.contains(posToCheck)) continue; // Positive x is east, negative x is west - if (level.isEmptyBlock(posToCheck)) + if (isPassable(level, posToCheck)) { - BlockPos westPos = posToCheck; - BlockPos eastPos = posToCheck.east(); + PosAndDepth westPos = posToCheck; + PosAndDepth eastPos = posToCheck.east(); - while (level.isEmptyBlock(westPos) && westPos.getX() >= bounds.minX()) + while (isPassable(level, westPos)) { checked.add(westPos); - expand(queue, checked, checker, bounds, level, westPos); - westPos = westPos.west(); + + if (westPos.depth() < maxDepth) + { + expand(queue, checked, checker, level, westPos); + westPos = westPos.west(); + } + else break; } - while (level.isEmptyBlock(eastPos) && eastPos.getX() <= bounds.maxX()) + while (isPassable(level, eastPos)) { checked.add(eastPos); - expand(queue, checked, checker, bounds, level, eastPos); - eastPos = eastPos.east(); + + if (eastPos.depth() < maxDepth) + { + expand(queue, checked, checker, level, eastPos); + eastPos = eastPos.east(); + } + else break; } // Add the first non-air blocks (or nothing if still air) - if (level.isEmptyBlock(westPos)) checked.add(westPos); - else checkPos(checked, checker, level, westPos); - - if (level.isEmptyBlock(eastPos)) checked.add(eastPos); - else checkPos(checked, checker, level, eastPos); + if (!isPassable(level, westPos)) checkPos(checked, checker, level, westPos); + if (!isPassable(level, eastPos)) checkPos(checked, checker, level, eastPos); } else { @@ -67,46 +74,73 @@ public static void fill(Level level, BlockPos pos, PositionChecker checker) } } - private static void expand(Queue queue, Set checked, PositionChecker checker, BoundingBox bounds, Level level, BlockPos pos) + private static void expand(Queue queue, Set checked, PositionChecker checker, Level level, PosAndDepth pos) { - BlockPos north = pos.north(); // Negative Z - BlockPos south = pos.south(); // Positive Z - BlockPos down = pos.below(); // Negative Y - BlockPos up = pos.above(); // Positive Y + PosAndDepth north = pos.north(); // Negative Z + PosAndDepth south = pos.south(); // Positive Z + PosAndDepth down = pos.below(); // Negative Y + PosAndDepth up = pos.above(); // Positive Y + + if (isPassable(level, north)) queue.add(north); + else checkPos(checked, checker, level, north); + + if (isPassable(level, south)) queue.add(south); + else checkPos(checked, checker, level, south); + + if (isPassable(level, down)) queue.add(down); + else checkPos(checked, checker, level, down); + + if (isPassable(level, up)) queue.add(up); + else checkPos(checked, checker, level, up); + } + + private static void checkPos(Set checked, PositionChecker checker, Level level, PosAndDepth pos) + { + checked.add(pos); + checker.check(level, pos); + } + + private static boolean isPassable(Level level, PosAndDepth pos) + { + BlockState state = level.getBlockState(pos.pos()); + return state.isAir() || !state.isSolid(); + } - if (north.getZ() >= bounds.minZ()) + public interface PositionChecker + { + void check(Level level, PosAndDepth pos); + } + + public record PosAndDepth(BlockPos pos, int depth) + { + public PosAndDepth north() { - if (level.isEmptyBlock(north)) queue.add(north); - else checkPos(checked, checker, level, north); + return new PosAndDepth(pos().north(), depth() + 1); } - if (south.getZ() <= bounds.maxZ()) + public PosAndDepth south() { - if (level.isEmptyBlock(south)) queue.add(south); - else checkPos(checked, checker, level, south); + return new PosAndDepth(pos().south(), depth() + 1); } - if (down.getY() >= bounds.minY()) + public PosAndDepth east() { - if (level.isEmptyBlock(down)) queue.add(down); - else checkPos(checked, checker, level, down); + return new PosAndDepth(pos().east(), depth() + 1); } - if (up.getY() <= bounds.maxY()) + public PosAndDepth west() { - if (level.isEmptyBlock(up)) queue.add(up); - else checkPos(checked, checker, level, up); + return new PosAndDepth(pos().west(), depth() + 1); } - } - private static void checkPos(Set checked, PositionChecker checker, Level level, BlockPos pos) - { - checked.add(pos); - checker.check(level, pos); - } + public PosAndDepth above() + { + return new PosAndDepth(pos().above(), depth() + 1); + } - public interface PositionChecker - { - void check(Level level, BlockPos pos); + public PosAndDepth below() + { + return new PosAndDepth(pos().below(), depth() + 1); + } } } diff --git a/common/src/main/java/toughasnails/temperature/TemperatureHelperImpl.java b/common/src/main/java/toughasnails/temperature/TemperatureHelperImpl.java index 989455d1..6569c0c6 100644 --- a/common/src/main/java/toughasnails/temperature/TemperatureHelperImpl.java +++ b/common/src/main/java/toughasnails/temperature/TemperatureHelperImpl.java @@ -195,7 +195,7 @@ private static TemperatureLevel proximityModifier(Level level, BlockPos pos, Tem pos = pos.above(); AreaFill.fill(level, pos, (checkerLevel, checkedPos) -> { - addHeatingOrCooling(heating, cooling, checkerLevel, checkedPos); + addHeatingOrCooling(heating, cooling, checkerLevel, checkedPos.pos()); }); if (heating.size() > cooling.size()) current = current.increment(1);