Possible fix for #986 - "Disks Disappearing"

This commit is contained in:
raoulvdberge
2017-05-13 14:55:37 +02:00
parent c6bd193313
commit 492afce309
11 changed files with 133 additions and 201 deletions

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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());
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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());

View File

@@ -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();