Skip to content

Commit

Permalink
Refactor temperature filling. Closes #789 and #713
Browse files Browse the repository at this point in the history
  • Loading branch information
Adubbz committed Jan 6, 2024
1 parent 37f5cb2 commit 700c5c3
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,14 @@ private static Set<ConnectedBlock> 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;
}
Expand All @@ -78,7 +80,7 @@ private static void populateConnectedBlocksForPlayer(Player player)

Set<BlockPos> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
Expand Down
128 changes: 81 additions & 47 deletions common/src/main/java/toughasnails/temperature/AreaFill.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<BlockPos> checked = Sets.newHashSet();
Queue<BlockPos> 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<PosAndDepth> checked = Sets.newHashSet();
Queue<PosAndDepth> 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
{
Expand All @@ -67,46 +74,73 @@ public static void fill(Level level, BlockPos pos, PositionChecker checker)
}
}

private static void expand(Queue<BlockPos> queue, Set<BlockPos> checked, PositionChecker checker, BoundingBox bounds, Level level, BlockPos pos)
private static void expand(Queue<PosAndDepth> queue, Set<PosAndDepth> 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<PosAndDepth> 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<BlockPos> 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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 700c5c3

Please sign in to comment.