Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for WorldSaveData dimension handling (#1398) and fluid in pipes… #1399

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/main/java/gregtech/api/pipenet/PipeNet.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

public abstract class PipeNet<NodeDataType> implements INBTSerializable<NBTTagCompound> {

protected final WorldPipeNet<NodeDataType, PipeNet<NodeDataType>> worldData;
protected WorldPipeNet<NodeDataType, PipeNet<NodeDataType>> worldData;
private final Map<BlockPos, Node<NodeDataType>> nodeByBlockPos = new HashMap<>();
private final Map<BlockPos, Node<NodeDataType>> unmodifiableNodeByBlockPos = Collections.unmodifiableMap(nodeByBlockPos);
private final Map<ChunkPos, Integer> ownedChunks = new HashMap<>();
Expand All @@ -31,6 +31,12 @@ public PipeNet(WorldPipeNet<NodeDataType, ? extends PipeNet> world) {
this.worldData = (WorldPipeNet<NodeDataType, PipeNet<NodeDataType>>) world;
}

void setWorldData(WorldPipeNet<NodeDataType, ? extends PipeNet> worldData) {
this.worldData = (WorldPipeNet<NodeDataType, PipeNet<NodeDataType>>) worldData;
// Duplicated from WorldPipeNet.onWorldSet()
onConnectionsUpdate();
}

public Set<ChunkPos> getContainedChunks() {
return Collections.unmodifiableSet(ownedChunks.keySet());
}
Expand Down
61 changes: 54 additions & 7 deletions src/main/java/gregtech/api/pipenet/WorldPipeNet.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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<NodeDataType, T extends PipeNet<NodeDataType>> extends WorldSavedData {

private World world;
protected boolean isFirstTick = true;
private WeakReference<World> worldRef = new WeakReference<>(null);
protected List<T> pipeNets = new ArrayList<>();
protected Map<ChunkPos, List<T>> pipeNetsByChunk = new HashMap<>();
protected WorldPipeNet<NodeDataType, T> 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>(world);
onWorldSet();
}
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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<T> 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<>();
Expand Down
12 changes: 9 additions & 3 deletions src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,22 @@ public static void registerTickablePipeNet(Function<World, TickableWorldPipeNet<

@SubscribeEvent
public static void onWorldTick(WorldTickEvent event) {
getPipeNetsForWorld(event.world).forEach(TickableWorldPipeNet::update);
final World world = event.world;
if (!world.isRemote)
getPipeNetsForWorld(world).forEach(TickableWorldPipeNet::update);
}

@SubscribeEvent
public static void onChunkLoad(ChunkEvent.Load event) {
getPipeNetsForWorld(event.getWorld()).forEach(it -> 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()));
}
}
2 changes: 2 additions & 0 deletions src/main/java/gregtech/common/pipelike/cable/BlockCable.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/gregtech/common/pipelike/cable/net/WorldENet.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@

public class WorldENet extends WorldPipeNet<WireProperties, EnergyNet> {

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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ public boolean canPushIntoFluidHandler(IPipeTile<FluidPipeType, FluidPipePropert

@Override
public void onEntityCollision(World worldIn, BlockPos pos, IBlockState state, Entity entityIn) {
if (worldIn.isRemote)
return;
if (entityIn instanceof EntityLivingBase && entityIn.world.getWorldTime() % 20 == 0L) {
EntityLivingBase entityLiving = (EntityLivingBase) entityIn;
FluidPipeNet pipeNet = getWorldPipeNet(worldIn).getNetFromPos(pos);
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetTank.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ public int fill(FluidStack resource, boolean doFill) {
handle.destroyNetwork(isLeakingPipe, isBurningPipe);
return copyStack.amount;
}
return super.fill(copyStack, doFill);
int result = super.fill(copyStack, doFill);
if (result != 0 && doFill)
this.handle.markDirty();
return result;
}

@Override
Expand All @@ -47,6 +50,7 @@ public FluidStack drain(FluidStack resource, boolean doDrain) {
resource.amount = originalAmount;
if (resultDrained != null && doDrain) {
drainedThisTick.increment(handle.getWorldData(), resultDrained.amount);
this.handle.markDirty();
}
return resultDrained;
}
Expand All @@ -61,6 +65,7 @@ public FluidStack drain(int maxDrain, boolean doDrain) {
FluidStack resultDrained = super.drain(maxDrain, doDrain);
if (resultDrained != null && doDrain) {
drainedThisTick.increment(handle.getWorldData(), resultDrained.amount);
this.handle.markDirty();
}
return resultDrained;
}
Expand All @@ -69,6 +74,7 @@ public void updateTankCapacity(int newTankCapacity) {
this.capacity = newTankCapacity;
if (this.fluid != null) {
this.fluid.amount = Math.min(this.fluid.amount, newTankCapacity);
this.handle.markDirty();
}
}

Expand Down
18 changes: 18 additions & 0 deletions src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidPipeNet.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;

Expand Down Expand Up @@ -109,6 +110,10 @@ protected void transferNodeData(Map<BlockPos, Node<FluidPipeProperties>> transfe
}
}

protected void markDirty() {
this.worldData.markDirty();
}

@Override
protected boolean areNodesCustomContactable(FluidPipeProperties first, FluidPipeProperties second, PipeNet<FluidPipeProperties> secondNodeNet) {
FluidPipeNet fluidPipeNet = (FluidPipeNet) secondNodeNet;
Expand All @@ -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"));
}
}
11 changes: 10 additions & 1 deletion src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@

public class WorldFluidPipeNet extends WorldPipeNet<FluidPipeProperties, FluidPipeNet> {

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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

public class WorldInventoryPipeNet extends TickableWorldPipeNet<EmptyNodeData, InventoryPipeNet> {

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);
Expand Down