Skip to content

Commit

Permalink
Fix Invalid Pipe Updates (#193)
Browse files Browse the repository at this point in the history
  • Loading branch information
aderoian authored Dec 11, 2024
1 parent b1b907e commit 13474fd
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package rearth.oritech.block.blocks.pipes;

import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext;
import net.minecraft.block.*;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.sound.SoundCategory;
Expand All @@ -27,6 +24,7 @@
import rearth.oritech.item.tools.Wrench;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public abstract class GenericPipeBlock extends Block implements Wrench.Wrenchable {
Expand Down Expand Up @@ -147,9 +145,15 @@ public BlockState getStateForNeighborUpdate(BlockState state, Direction directio

// transform to interface when machine is placed as neighbor
if (hasMachineInDirection(direction, world, pos, apiValidationFunction())) {
// Only update if the neighbor is a new machine
var hasMachine = getNetworkData(world).machinePipeNeighbors.getOrDefault(neighborPos, HashSet.newHashSet(0)).contains(direction.getOpposite());
if (hasMachine) return state;

var connectionBlock = getConnectionBlock();
return ((GenericPipeBlock) connectionBlock.getBlock()).addConnectionStates(connectionBlock, world, pos, direction);
}
} else if (neighborState.isOf(Blocks.AIR))
// remove potential stale machine -> neighboring pipes mapping
getNetworkData(world).machinePipeNeighbors.remove(neighborPos);

return state;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
Expand All @@ -17,6 +18,8 @@
import rearth.oritech.Oritech;
import rearth.oritech.block.entity.pipes.GenericPipeInterfaceEntity;

import java.util.HashSet;

public abstract class GenericPipeConnectionBlock extends GenericPipeBlock implements BlockEntityProvider {

public GenericPipeConnectionBlock(Settings settings) {
Expand Down Expand Up @@ -46,13 +49,20 @@ public BlockState getStateForNeighborUpdate(BlockState state, Direction directio
if (worldImp.isClient) return state;

if (!hasNeighboringMachine(state, worldImp, pos, false)) {
// remove stale machine -> neighboring pipes mapping
GenericPipeInterfaceEntity.removeStaleMachinePipeNeighbors(pos, getNetworkData(worldImp));

var normalState = getNormalBlock();
return ((GenericPipeBlock) normalState.getBlock()).addConnectionStates(normalState, worldImp, pos, false);
}

var interfaceState = state;
if (!(neighborState.getBlock() instanceof GenericPipeBlock)) {
interfaceState = addConnectionStates(state, worldImp, pos, direction);
// only update connection if neighbor is a new machine
var hadMachine = getNetworkData(worldImp).machinePipeNeighbors.getOrDefault(neighborPos, HashSet.newHashSet(0)).contains(direction.getOpposite());
if (state.isOf(Blocks.AIR) || !hadMachine) {
interfaceState = addConnectionStates(state, worldImp, pos, direction);
}

if (!interfaceState.equals(state)) {
// reload connection when state has changed (e.g. machine added/removed)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtList;
import net.minecraft.nbt.NbtLong;
import net.minecraft.nbt.*;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.util.Pair;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.PersistentState;
import org.jetbrains.annotations.Nullable;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import rearth.oritech.Oritech;
import rearth.oritech.block.blocks.pipes.GenericPipeBlock;
import rearth.oritech.block.entity.interaction.PipeBoosterBlockEntity;
Expand Down Expand Up @@ -77,14 +75,22 @@ public static void addNode(World world, BlockPos pos, boolean isInterface, Block
Oritech.LOGGER.debug("registering/updating node: " + pos);

data.pipes.add(pos);
if (isInterface) {
var connectedMachines = new HashSet<BlockPos>(6);
var block = (GenericPipeBlock) newState.getBlock();
for (var neighbor : Direction.values()) {
if (block.isConnectingInDirection(newState, neighbor, false) && block.hasMachineInDirection(neighbor, world, pos, block.apiValidationFunction()))
var connectedMachines = new HashSet<BlockPos>(6);
var block = (GenericPipeBlock) newState.getBlock();
for (var neighbor : Direction.values()) {
var neighborPos = pos.offset(neighbor);
var neighborMap = data.machinePipeNeighbors.getOrDefault(neighborPos, new HashSet<>());
if (block.hasMachineInDirection(neighbor, world, pos, block.apiValidationFunction())) {
if (block.isConnectingInDirection(newState, neighbor, false))
connectedMachines.add(pos.offset(neighbor));

neighborMap.add(neighbor.getOpposite());
}

if (!neighborMap.isEmpty()) data.machinePipeNeighbors.put(neighborPos, neighborMap);
}

if (isInterface) {
data.machineInterfaces.put(pos, connectedMachines);
} else {
data.machineInterfaces.remove(pos);
Expand All @@ -94,13 +100,15 @@ public static void addNode(World world, BlockPos pos, boolean isInterface, Block
}

public static void removeNode(World world, BlockPos pos, boolean wasInterface, BlockState oldState, PipeNetworkData data) {
Oritech.LOGGER.debug("removing node: " + pos);
Oritech.LOGGER.debug("removing node: " + pos + " | " + wasInterface);

var oldNetwork = data.pipeNetworkLinks.getOrDefault(pos, -1);

data.pipes.remove(pos);
if (wasInterface) data.machineInterfaces.remove(pos);

removeStaleMachinePipeNeighbors(pos, data);

data.pipeNetworks.remove(oldNetwork);
data.pipeNetworkInterfaces.remove(oldNetwork);
data.pipeNetworkLinks.remove(pos);
Expand Down Expand Up @@ -178,6 +186,27 @@ public static Set<Pair<BlockPos, Direction>> findNetworkTargets(BlockPos from, P
return data.pipeNetworkInterfaces.get(connectedNetwork);
}

/**
* Removes any stale machine -> neighboring pipes mappings
* Used when a pipe node is destroyed
*
* @param pos position of the destroyed node
* @param data network data
*/
public static void removeStaleMachinePipeNeighbors(BlockPos pos, PipeNetworkData data) {
for (var neighbor : Direction.values()) {
var machine = pos.offset(neighbor);
var machineNeighbors = data.machinePipeNeighbors.get(machine);
if (machineNeighbors == null) continue;

machineNeighbors.remove(Direction.getFacing(Vec3d.of(pos.subtract(machine))));
if (machineNeighbors.isEmpty())
data.machinePipeNeighbors.remove(machine);
else
data.machinePipeNeighbors.put(machine, machineNeighbors);
}
}

private static class FloodFillSearch {

final HashSet<BlockPos> checkedPositions = new HashSet<>();
Expand Down Expand Up @@ -257,6 +286,8 @@ public static final class PipeNetworkData extends PersistentState {
public final HashMap<Integer, Set<BlockPos>> pipeNetworks = new HashMap<>(); // networks are never updated, and instead always replaced by new ones with different ids
public final HashMap<Integer, Set<Pair<BlockPos, Direction>>> pipeNetworkInterfaces = new HashMap<>(); // list of machines that are connected to the network

public final HashMap<BlockPos, Set<Direction>> machinePipeNeighbors = new HashMap<>(); // List of neighboring pipes per machine, and the direction they are in. Missing direction means no connection

@Override
public int hashCode() {
int result = pipeNetworkLinks.hashCode();
Expand Down Expand Up @@ -332,6 +363,21 @@ public static PipeNetworkData fromNbt(NbtCompound nbt, RegistryWrapper.WrapperLo
}
}

// Deserialize machinePipeNeighbors
if (nbt.contains("machinePipeNeighbors", NbtElement.COMPOUND_TYPE)) {
var connectionPipeNeighborsNbt = nbt.getCompound("machinePipeNeighbors");
for (var key : connectionPipeNeighborsNbt.getKeys()) {
var pos = BlockPos.fromLong(Long.parseLong(key));
var neighborsList = connectionPipeNeighborsNbt.getList(key, NbtElement.STRING_TYPE);
var neighbors = new HashSet<Direction>();
for (var neighborElement : neighborsList) {
var direction = Direction.byName(neighborElement.asString());
neighbors.add(direction);
}
result.machinePipeNeighbors.put(pos, neighbors);
}
}

result.markDirty();

return result;
Expand Down Expand Up @@ -383,6 +429,18 @@ public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup regis
});
nbt.put("pipeNetworkInterfaces", pipeNetworkInterfacesNbt);

// Serialize machinePipeNeighbors
var connectionPipeNeighborsNbt = new NbtCompound();
machinePipeNeighbors.forEach((pos, neighbors) -> {
var neighborsList = new NbtList();
neighbors.forEach(direction -> {
var nbtElement = NbtString.of(direction.getName());
neighborsList.add(nbtElement);
});
connectionPipeNeighborsNbt.put(Long.toString(pos.asLong()), neighborsList);
});
nbt.put("machinePipeNeighbors", connectionPipeNeighborsNbt);

return nbt;
}
}
Expand Down

0 comments on commit 13474fd

Please sign in to comment.