Possible fix for #986 - "Disks Disappearing"
This commit is contained in:
@@ -37,17 +37,14 @@ public interface IRSAPI {
|
||||
INetworkNodeRegistry getNetworkNodeRegistry();
|
||||
|
||||
/**
|
||||
* @param dimension the dimension
|
||||
* @return the network node manager for the given dimension
|
||||
*/
|
||||
INetworkNodeManager getNetworkNodeManager(int dimension);
|
||||
|
||||
/**
|
||||
* Marks the network node saved data dirty for a given world.
|
||||
* Gets a network node manager for a given world.
|
||||
* This can only be called on the server side!
|
||||
* There is no such concept of a network node manager on the client.
|
||||
*
|
||||
* @param world the world
|
||||
* @return the network node manager for the given world
|
||||
*/
|
||||
void markNetworkNodesDirty(World world);
|
||||
INetworkNodeManager getNetworkNodeManager(World world);
|
||||
|
||||
/**
|
||||
* @return the default storage disk behavior
|
||||
|
||||
@@ -21,10 +21,9 @@ public interface INetworkNodeManager {
|
||||
/**
|
||||
* Removes a node from the registry at a given position.
|
||||
*
|
||||
* @param pos the position of the node
|
||||
* @param notifyClient true to notify the client of the removal, false otherwise
|
||||
* @param pos the position of the node
|
||||
*/
|
||||
void removeNode(BlockPos pos, boolean notifyClient);
|
||||
void removeNode(BlockPos pos);
|
||||
|
||||
/**
|
||||
* Sets a node in the registry at a given position.
|
||||
@@ -43,4 +42,9 @@ public interface INetworkNodeManager {
|
||||
* Clears all the nodes.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Marks the network node manager for saving.
|
||||
*/
|
||||
void markForSaving();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPrev
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.registry.CraftingTaskRegistry;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.network.NetworkNodeManager;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.network.NetworkNodeRegistry;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.network.node.WorldSavedDataNetworkNode;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.network.readerwriter.ReaderWriterChannel;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.network.readerwriter.ReaderWriterHandlerRegistry;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.solderer.SoldererRegistry;
|
||||
@@ -38,9 +37,7 @@ import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.fml.common.discovery.ASMDataTable;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -53,8 +50,7 @@ public class API implements IRSAPI {
|
||||
|
||||
private IComparer comparer = new Comparer();
|
||||
private INetworkNodeRegistry networkNodeRegistry = new NetworkNodeRegistry();
|
||||
private Map<Integer, INetworkNodeManager> networkNodeProviderServer = new HashMap<>();
|
||||
private Map<Integer, INetworkNodeManager> networkNodeProviderClient = new HashMap<>();
|
||||
private Map<Integer, INetworkNodeManager> networkNodeManagers = new HashMap<>();
|
||||
private IStorageDiskBehavior storageDiskBehavior = new StorageDiskBehavior();
|
||||
private ISoldererRegistry soldererRegistry = new SoldererRegistry();
|
||||
private ICraftingTaskRegistry craftingTaskRegistry = new CraftingTaskRegistry();
|
||||
@@ -97,15 +93,12 @@ public class API implements IRSAPI {
|
||||
}
|
||||
|
||||
@Override
|
||||
public INetworkNodeManager getNetworkNodeManager(final int dimension) {
|
||||
Map<Integer, INetworkNodeManager> provider = FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT ? networkNodeProviderClient : networkNodeProviderServer;
|
||||
public INetworkNodeManager getNetworkNodeManager(World world) {
|
||||
if (world.isRemote) {
|
||||
throw new IllegalStateException("Attempting to access network node manager on the client");
|
||||
}
|
||||
|
||||
return provider.computeIfAbsent(dimension, r -> new NetworkNodeManager(dimension));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markNetworkNodesDirty(World world) {
|
||||
WorldSavedDataNetworkNode.getOrLoadData(world).markDirty();
|
||||
return networkNodeManagers.computeIfAbsent(world.provider.getDimension(), m -> NetworkNodeManager.getManager(world));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,29 +5,29 @@ import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
|
||||
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeProxy;
|
||||
import com.raoulvdberge.refinedstorage.api.network.security.Permission;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.network.node.WorldSavedDataNetworkNode;
|
||||
import com.raoulvdberge.refinedstorage.proxy.CapabilityNetworkNodeProxy;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraftforge.event.world.BlockEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
public class NetworkNodeListener {
|
||||
@SubscribeEvent
|
||||
public void onWorldTick(TickEvent.WorldTickEvent e) {
|
||||
e.world.profiler.startSection("network node ticking");
|
||||
if (!e.world.isRemote) {
|
||||
e.world.profiler.startSection("network node ticking");
|
||||
|
||||
if (e.phase == TickEvent.Phase.END) {
|
||||
for (INetworkNode node : API.instance().getNetworkNodeManager(e.world.provider.getDimension()).all()) {
|
||||
if (e.world.isBlockLoaded(node.getPos())) {
|
||||
node.update();
|
||||
if (e.phase == TickEvent.Phase.END) {
|
||||
for (INetworkNode node : API.instance().getNetworkNodeManager(e.world).all()) {
|
||||
if (e.world.isBlockLoaded(node.getPos())) {
|
||||
node.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e.world.profiler.endSection();
|
||||
e.world.profiler.endSection();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
@@ -69,12 +69,4 @@ public class NetworkNodeListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onWorldLoad(WorldEvent.Load e) {
|
||||
// Clear all data from a possible previous load, so we start with a clean slate
|
||||
API.instance().getNetworkNodeManager(e.getWorld().provider.getDimension()).clear();
|
||||
|
||||
WorldSavedDataNetworkNode.getOrLoadData(e.getWorld());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,107 @@
|
||||
package com.raoulvdberge.refinedstorage.apiimpl.network;
|
||||
|
||||
import com.raoulvdberge.refinedstorage.RS;
|
||||
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
|
||||
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeManager;
|
||||
import com.raoulvdberge.refinedstorage.network.MessageNodeRemove;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldSavedData;
|
||||
import net.minecraft.world.storage.MapStorage;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NetworkNodeManager extends WorldSavedData implements INetworkNodeManager {
|
||||
private static final String NAME = "refinedstorage_nodes";
|
||||
|
||||
private static final String NBT_NODES = "Nodes";
|
||||
private static final String NBT_NODE_ID = "Id";
|
||||
private static final String NBT_NODE_DATA = "Data";
|
||||
private static final String NBT_NODE_POS = "Pos";
|
||||
|
||||
public class NetworkNodeManager implements INetworkNodeManager {
|
||||
private Map<BlockPos, INetworkNode> nodes = new HashMap<>();
|
||||
|
||||
private int dimension;
|
||||
|
||||
public NetworkNodeManager(int dimension) {
|
||||
this.dimension = dimension;
|
||||
public NetworkNodeManager(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(NBTTagCompound tag) {
|
||||
System.out.println("[RS DEBUG] Reading network nodes, first clearing data...");
|
||||
|
||||
clear();
|
||||
|
||||
NBTTagList list = tag.getTagList(NBT_NODES, Constants.NBT.TAG_COMPOUND);
|
||||
|
||||
for (int i = 0; i < list.tagCount(); ++i) {
|
||||
NBTTagCompound nodeTag = list.getCompoundTagAt(i);
|
||||
|
||||
String id = nodeTag.getString(NBT_NODE_ID);
|
||||
NBTTagCompound data = nodeTag.getCompoundTag(NBT_NODE_DATA);
|
||||
BlockPos pos = BlockPos.fromLong(nodeTag.getLong(NBT_NODE_POS));
|
||||
|
||||
Function<NBTTagCompound, INetworkNode> factory = API.instance().getNetworkNodeRegistry().get(id);
|
||||
|
||||
if (factory != null) {
|
||||
setNode(pos, factory.apply(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
|
||||
System.out.println("[RS DEBUG] Writing network nodes");
|
||||
|
||||
NBTTagList list = new NBTTagList();
|
||||
|
||||
for (INetworkNode node : all()) {
|
||||
NBTTagCompound nodeTag = new NBTTagCompound();
|
||||
|
||||
nodeTag.setString(NBT_NODE_ID, node.getId());
|
||||
nodeTag.setLong(NBT_NODE_POS, node.getPos().toLong());
|
||||
nodeTag.setTag(NBT_NODE_DATA, node.write(new NBTTagCompound()));
|
||||
|
||||
list.appendTag(nodeTag);
|
||||
}
|
||||
|
||||
tag.setTag(NBT_NODES, list);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static NetworkNodeManager getManager(World world) {
|
||||
MapStorage storage = world.getPerWorldStorage();
|
||||
NetworkNodeManager instance = (NetworkNodeManager) storage.getOrLoadData(NetworkNodeManager.class, NAME);
|
||||
|
||||
if (instance == null) {
|
||||
System.out.println("[RS DEBUG] Initializing Network Node Manager for " + world.provider.getDimension());
|
||||
instance = new NetworkNodeManager(NAME);
|
||||
|
||||
storage.setData(NAME, instance);
|
||||
} else {
|
||||
System.out.println("[RS DEBUG] Network Node Manager for " + world.provider.getDimension() + " already exists, OK...");
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public INetworkNode getNode(BlockPos pos) {
|
||||
return nodes.get(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNode(BlockPos pos, boolean notifyClient) {
|
||||
nodes.remove(pos);
|
||||
public void removeNode(BlockPos pos) {
|
||||
System.out.println("[RS DEBUG] Removing node at " + pos);
|
||||
|
||||
if (notifyClient) {
|
||||
RS.INSTANCE.network.sendToAll(new MessageNodeRemove(dimension, pos));
|
||||
}
|
||||
nodes.remove(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,6 +116,12 @@ public class NetworkNodeManager implements INetworkNodeManager {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
System.out.println("[RS DEBUG] Clearing data!");
|
||||
nodes.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markForSaving() {
|
||||
markDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ public abstract class NetworkNode implements INetworkNode, INetworkNeighborhoodA
|
||||
|
||||
@Override
|
||||
public void markDirty() {
|
||||
if (holder.world() != null) {
|
||||
API.instance().markNetworkNodesDirty(holder.world());
|
||||
if (holder.world() != null && !holder.world().isRemote) {
|
||||
API.instance().getNetworkNodeManager(holder.world()).markForSaving();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
package com.raoulvdberge.refinedstorage.apiimpl.network.node;
|
||||
|
||||
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldSavedData;
|
||||
import net.minecraft.world.storage.MapStorage;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class WorldSavedDataNetworkNode extends WorldSavedData {
|
||||
private static final String NAME = "refinedstorage_nodes";
|
||||
|
||||
private static final String NBT_NODES = "Nodes";
|
||||
private static final String NBT_NODE_ID = "Id";
|
||||
private static final String NBT_NODE_DATA = "Data";
|
||||
private static final String NBT_NODE_POS = "Pos";
|
||||
private static final String NBT_DIMENSION = "Dimension";
|
||||
|
||||
private int dimension;
|
||||
|
||||
public WorldSavedDataNetworkNode(int dimension) {
|
||||
super(NAME);
|
||||
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
public WorldSavedDataNetworkNode(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromNBT(NBTTagCompound tag) {
|
||||
if (tag.hasKey(NBT_NODES) && tag.hasKey(NBT_DIMENSION)) {
|
||||
dimension = tag.getInteger(NBT_DIMENSION);
|
||||
|
||||
NBTTagList list = tag.getTagList(NBT_NODES, Constants.NBT.TAG_COMPOUND);
|
||||
|
||||
for (int i = 0; i < list.tagCount(); ++i) {
|
||||
NBTTagCompound nodeTag = list.getCompoundTagAt(i);
|
||||
|
||||
String id = nodeTag.getString(NBT_NODE_ID);
|
||||
NBTTagCompound data = nodeTag.getCompoundTag(NBT_NODE_DATA);
|
||||
BlockPos pos = BlockPos.fromLong(nodeTag.getLong(NBT_NODE_POS));
|
||||
|
||||
Function<NBTTagCompound, INetworkNode> factory = API.instance().getNetworkNodeRegistry().get(id);
|
||||
|
||||
if (factory != null) {
|
||||
API.instance().getNetworkNodeManager(dimension).setNode(pos, factory.apply(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound writeToNBT(NBTTagCompound tag) {
|
||||
NBTTagList list = new NBTTagList();
|
||||
|
||||
for (INetworkNode node : API.instance().getNetworkNodeManager(dimension).all()) {
|
||||
NBTTagCompound nodeTag = new NBTTagCompound();
|
||||
|
||||
nodeTag.setString(NBT_NODE_ID, node.getId());
|
||||
nodeTag.setLong(NBT_NODE_POS, node.getPos().toLong());
|
||||
nodeTag.setTag(NBT_NODE_DATA, node.write(new NBTTagCompound()));
|
||||
|
||||
list.appendTag(nodeTag);
|
||||
}
|
||||
|
||||
tag.setTag(NBT_NODES, list);
|
||||
|
||||
tag.setInteger(NBT_DIMENSION, dimension);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
public static WorldSavedDataNetworkNode getOrLoadData(World world) {
|
||||
MapStorage storage = world.getPerWorldStorage();
|
||||
WorldSavedDataNetworkNode instance = (WorldSavedDataNetworkNode) storage.getOrLoadData(WorldSavedDataNetworkNode.class, NAME);
|
||||
|
||||
if (instance == null) {
|
||||
instance = new WorldSavedDataNetworkNode(world.provider.getDimension());
|
||||
|
||||
storage.setData(NAME, instance);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public abstract class BlockNode extends BlockBase {
|
||||
|
||||
@Override
|
||||
public void breakBlock(World world, BlockPos pos, IBlockState state) {
|
||||
INetworkNodeManager manager = API.instance().getNetworkNodeManager(world.provider.getDimension());
|
||||
INetworkNodeManager manager = API.instance().getNetworkNodeManager(world);
|
||||
|
||||
INetworkNode node = manager.getNode(pos);
|
||||
|
||||
@@ -58,9 +58,8 @@ public abstract class BlockNode extends BlockBase {
|
||||
|
||||
removeTile(world, pos, state);
|
||||
|
||||
manager.removeNode(pos, true);
|
||||
|
||||
API.instance().markNetworkNodesDirty(world);
|
||||
manager.removeNode(pos);
|
||||
manager.markForSaving();
|
||||
|
||||
if (node.getNetwork() != null) {
|
||||
node.getNetwork().getNodeGraph().rebuild();
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.raoulvdberge.refinedstorage.network;
|
||||
|
||||
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeManager;
|
||||
import com.raoulvdberge.refinedstorage.apiimpl.API;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||
|
||||
public class MessageNodeRemove implements IMessage, IMessageHandler<MessageNodeRemove, IMessage> {
|
||||
private int dim;
|
||||
private BlockPos pos;
|
||||
|
||||
public MessageNodeRemove() {
|
||||
}
|
||||
|
||||
public MessageNodeRemove(int dim, BlockPos pos) {
|
||||
this.dim = dim;
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf) {
|
||||
dim = buf.readInt();
|
||||
pos = BlockPos.fromLong(buf.readLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf) {
|
||||
buf.writeInt(dim);
|
||||
buf.writeLong(pos.toLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMessage onMessage(MessageNodeRemove message, MessageContext ctx) {
|
||||
Minecraft.getMinecraft().addScheduledTask(() -> {
|
||||
INetworkNodeManager manager = API.instance().getNetworkNodeManager(message.dim);
|
||||
|
||||
manager.removeNode(message.pos, false);
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,6 @@ public class ProxyCommon {
|
||||
RS.INSTANCE.network.registerMessage(MessageReaderWriterChannelRemove.class, MessageReaderWriterChannelRemove.class, id++, Side.SERVER);
|
||||
RS.INSTANCE.network.registerMessage(MessageSecurityManagerUpdate.class, MessageSecurityManagerUpdate.class, id++, Side.SERVER);
|
||||
RS.INSTANCE.network.registerMessage(MessageWirelessFluidGridSettingsUpdate.class, MessageWirelessFluidGridSettingsUpdate.class, id++, Side.SERVER);
|
||||
RS.INSTANCE.network.registerMessage(MessageNodeRemove.class, MessageNodeRemove.class, id++, Side.CLIENT);
|
||||
RS.INSTANCE.network.registerMessage(MessageWirelessCraftingMonitorViewAutomated.class, MessageWirelessCraftingMonitorViewAutomated.class, id++, Side.SERVER);
|
||||
|
||||
NetworkRegistry.INSTANCE.registerGuiHandler(RS.INSTANCE, new GuiHandler());
|
||||
|
||||
@@ -25,6 +25,8 @@ public abstract class TileNode<N extends NetworkNode> extends TileBase implement
|
||||
|
||||
private NBTTagCompound legacyTag;
|
||||
|
||||
private N clientNode;
|
||||
|
||||
protected static final String NBT_ACTIVE = "Active";
|
||||
|
||||
public TileNode() {
|
||||
@@ -90,14 +92,21 @@ public abstract class TileNode<N extends NetworkNode> extends TileBase implement
|
||||
@Nonnull
|
||||
@SuppressWarnings("unchecked")
|
||||
public N getNode() {
|
||||
INetworkNodeManager manager = API.instance().getNetworkNodeManager(getWorld().provider.getDimension());
|
||||
if (getWorld().isRemote) {
|
||||
if (clientNode == null) {
|
||||
clientNode = createNode();
|
||||
}
|
||||
|
||||
return clientNode;
|
||||
}
|
||||
|
||||
INetworkNodeManager manager = API.instance().getNetworkNodeManager(getWorld());
|
||||
|
||||
NetworkNode node = (NetworkNode) manager.getNode(pos);
|
||||
|
||||
if (node == null) {
|
||||
manager.setNode(pos, node = createNode());
|
||||
|
||||
API.instance().markNetworkNodesDirty(getWorld());
|
||||
manager.markForSaving();
|
||||
}
|
||||
|
||||
if (node.getHolder().world() == null) {
|
||||
@@ -125,6 +134,8 @@ public abstract class TileNode<N extends NetworkNode> extends TileBase implement
|
||||
} else if (legacyTag.getSize() == 6 + 1 && hasMeta && hasForgeData && hasForgeCaps) {
|
||||
// NO OP
|
||||
} else {
|
||||
System.out.println("[RS DEBUG] Reading legacy tag for node at " + pos + "!");
|
||||
|
||||
node.read(legacyTag);
|
||||
node.markDirty();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user