diff --git a/src/main/java/gregtech/api/pipenet/PipeNet.java b/src/main/java/gregtech/api/pipenet/PipeNet.java index 1fba3d1daa..48681afe31 100644 --- a/src/main/java/gregtech/api/pipenet/PipeNet.java +++ b/src/main/java/gregtech/api/pipenet/PipeNet.java @@ -19,7 +19,7 @@ public abstract class PipeNet implements INBTSerializable { - protected final WorldPipeNet> worldData; + protected WorldPipeNet> worldData; private final Map> nodeByBlockPos = new HashMap<>(); private final Map> unmodifiableNodeByBlockPos = Collections.unmodifiableMap(nodeByBlockPos); private final Map ownedChunks = new HashMap<>(); @@ -31,6 +31,12 @@ public PipeNet(WorldPipeNet world) { this.worldData = (WorldPipeNet>) world; } + void setWorldData(WorldPipeNet worldData) { + this.worldData = (WorldPipeNet>) worldData; + // Duplicated from WorldPipeNet.onWorldSet() + onConnectionsUpdate(); + } + public Set getContainedChunks() { return Collections.unmodifiableSet(ownedChunks.keySet()); } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/pipenet/WorldPipeNet.java old mode 100644 new mode 100755 index 34245df2d9..6cabed1c1f --- a/src/main/java/gregtech/api/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNet.java @@ -9,27 +9,38 @@ import net.minecraft.world.storage.WorldSavedData; import net.minecraftforge.common.util.Constants.NBT; +import java.lang.ref.WeakReference; import java.util.*; +import gregtech.api.util.GTLog; + public abstract class WorldPipeNet> extends WorldSavedData { - private World world; - protected boolean isFirstTick = true; + private WeakReference worldRef = new WeakReference<>(null); protected List pipeNets = new ArrayList<>(); protected Map> pipeNetsByChunk = new HashMap<>(); + protected WorldPipeNet oldData = null; + protected boolean checkedForOldData = false; + + public static String getDataID(final String baseID, final World world) { + if (world == null || world.isRemote) + throw new RuntimeException("WorldPipeNet should only be created on the server!"); + final int dimension = world.provider.getDimension(); + return baseID + '.' + dimension; + } public WorldPipeNet(String name) { super(name); } public World getWorld() { - return world; + return this.worldRef.get(); } protected void setWorldAndInit(World world) { - if (isFirstTick) { - this.world = world; - this.isFirstTick = false; + // Reset the world as the dimensions are loaded/unloaded + if (world != this.worldRef.get()) { + this.worldRef = new WeakReference(world); onWorldSet(); } } @@ -101,7 +112,7 @@ public T getNetFromPos(BlockPos blockPos) { if (pipeNet.containsNode(blockPos)) return pipeNet; } - return null; + return checkForOldData(blockPos); } protected void addPipeNet(T pipeNet) { @@ -122,6 +133,42 @@ protected void removePipeNet(T pipeNet) { protected abstract T createNetInstance(); + /* + * This method is used when data cannot be found at the given position. + * + * It's purpose is to move pipenets from the old data file to new one based on matching block position + */ + private T checkForOldData(final BlockPos blockPos) { + // No old data + if (this.oldData == null || this.oldData.pipeNets.isEmpty()) + return null; + + // See if we have a pipenet for this block pos in the old data + T foundOldData = null; + final List oldPipeNets = this.oldData.pipeNetsByChunk.getOrDefault(new ChunkPos(blockPos), Collections.emptyList()); + for (T pipeNet : oldPipeNets) { + if (pipeNet.containsNode(blockPos)) { + if (foundOldData != null) { + // We have 2 pipenets at this position? + GTLog.logger.warn("Found duplicate pipenets in old data at {} [{},{}]", blockPos, foundOldData, pipeNet); + return null; + } + foundOldData = pipeNet; + } + } + // Nothing found + if (foundOldData == null) + return null; + // Move the old data into the new data + GTLog.logger.info("Fixing old data for {} found at {}", foundOldData, blockPos); + this.oldData.removePipeNet(foundOldData); + this.oldData.markDirty(); + this.addPipeNetSilently(foundOldData); + this.markDirty(); + foundOldData.setWorldData(this); + return foundOldData; + } + @Override public void readFromNBT(NBTTagCompound nbt) { this.pipeNets = new ArrayList<>(); diff --git a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java old mode 100644 new mode 100755 index d150da8573..6396f86854 --- a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java +++ b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java @@ -27,16 +27,22 @@ public static void registerTickablePipeNet(Function it.onChunkLoaded(event.getChunk())); + final World world = event.getWorld(); + if (!world.isRemote) + getPipeNetsForWorld(world).forEach(it -> it.onChunkLoaded(event.getChunk())); } @SubscribeEvent public static void onChunkUnload(ChunkEvent.Unload event) { - getPipeNetsForWorld(event.getWorld()).forEach(it -> it.onChunkUnloaded(event.getChunk())); + final World world = event.getWorld(); + if (!world.isRemote) + getPipeNetsForWorld(world).forEach(it -> it.onChunkUnloaded(event.getChunk())); } } diff --git a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java old mode 100644 new mode 100755 index 5cf1df9de1..9e5502f078 --- a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java @@ -105,6 +105,8 @@ public int getActiveNodeConnections(IBlockAccess world, BlockPos nodePos, IPipeT @Override public void onEntityCollision(World worldIn, BlockPos pos, IBlockState state, Entity entityIn) { + if (worldIn.isRemote) + return; Insulation insulation = getPipeTileEntity(worldIn, pos).getPipeType(); boolean damageOnLossless = ConfigHolder.doLosslessWiresDamage; if (!worldIn.isRemote && insulation.insulationLevel == -1 && entityIn instanceof EntityLivingBase) { diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldENet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldENet.java old mode 100644 new mode 100755 index 6bbba2a9ed..8c5dc3fdc5 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldENet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldENet.java @@ -6,14 +6,23 @@ public class WorldENet extends WorldPipeNet { - private static final String DATA_ID = "gregtech.e_net"; + private static final String DATA_ID_BASE = "gregtech.e_net"; public static WorldENet getWorldENet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); + // First look for saved data WorldENet eNetWorldData = (WorldENet) world.loadData(WorldENet.class, DATA_ID); + // No saved data, create it and queue it to be saved if (eNetWorldData == null) { eNetWorldData = new WorldENet(DATA_ID); world.setData(DATA_ID, eNetWorldData); } + // See if we have old data + if (!eNetWorldData.checkedForOldData) { + eNetWorldData.oldData = (WorldENet) world.loadData(WorldENet.class, DATA_ID_BASE); + eNetWorldData.checkedForOldData = true; + } + // Initialise eNetWorldData.setWorldAndInit(world); return eNetWorldData; } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java index a1e3e55a66..ef855c263d 100755 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java @@ -143,6 +143,8 @@ public boolean canPushIntoFluidHandler(IPipeTile> transfe } } + protected void markDirty() { + this.worldData.markDirty(); + } + @Override protected boolean areNodesCustomContactable(FluidPipeProperties first, FluidPipeProperties second, PipeNet secondNodeNet) { FluidPipeNet fluidPipeNet = (FluidPipeNet) secondNodeNet; @@ -132,4 +137,17 @@ protected FluidPipeProperties readNodeData(NBTTagCompound tagCompound) { return new FluidPipeProperties(maxTemperature, throughput, gasProof); } + @Override + public NBTTagCompound serializeNBT() { + final NBTTagCompound nbt = super.serializeNBT(); + nbt.setTag("FluidNetTank", this.fluidNetTank.writeToNBT(new NBTTagCompound())); + return nbt; + } + + @Override + public void deserializeNBT(final NBTTagCompound nbt) { + super.deserializeNBT(nbt); + if (nbt.hasKey("FluidNetTank", NBT.TAG_COMPOUND)) + this.fluidNetTank.readFromNBT(nbt.getCompoundTag("FluidNetTank")); + } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java old mode 100644 new mode 100755 index 3160f63aae..e1a7fd88cb --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -6,14 +6,23 @@ public class WorldFluidPipeNet extends WorldPipeNet { - private static final String DATA_ID = "gregtech.fluid_pipe_net"; + private static final String DATA_ID_BASE = "gregtech.fluid_pipe_net"; public static WorldFluidPipeNet getWorldPipeNet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); + // First look for saved data WorldFluidPipeNet netWorldData = (WorldFluidPipeNet) world.loadData(WorldFluidPipeNet.class, DATA_ID); + // No saved data, create it and queue it to be saved if (netWorldData == null) { netWorldData = new WorldFluidPipeNet(DATA_ID); world.setData(DATA_ID, netWorldData); } + // See if we have old data + if (!netWorldData.checkedForOldData) { + netWorldData.oldData = (WorldFluidPipeNet) world.loadData(WorldFluidPipeNet.class, DATA_ID_BASE); + netWorldData.checkedForOldData = true; + } + // Initialise netWorldData.setWorldAndInit(world); return netWorldData; } diff --git a/src/main/java/gregtech/common/pipelike/inventory/net/WorldInventoryPipeNet.java b/src/main/java/gregtech/common/pipelike/inventory/net/WorldInventoryPipeNet.java index b9566de0d3..f0f0882667 100644 --- a/src/main/java/gregtech/common/pipelike/inventory/net/WorldInventoryPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/inventory/net/WorldInventoryPipeNet.java @@ -6,9 +6,10 @@ public class WorldInventoryPipeNet extends TickableWorldPipeNet { - private static final String DATA_ID = "gregtech.inventory_pipe_net"; + private static final String DATA_ID_BASE = "gregtech.inventory_pipe_net"; public static WorldInventoryPipeNet getWorldPipeNet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); WorldInventoryPipeNet netWorldData = (WorldInventoryPipeNet) world.loadData(WorldInventoryPipeNet.class, DATA_ID); if (netWorldData == null) { netWorldData = new WorldInventoryPipeNet(DATA_ID);