From 324199828dca17525be842d8f92107a8da261d3d Mon Sep 17 00:00:00 2001 From: Darkere Date: Tue, 14 Jul 2020 15:40:11 +0200 Subject: [PATCH] 1.16 Save writing for data files (#2607) * implement safe writing for the disk file fixes #1846 * Extract safe writing into extra class rework the saving of NetworkManager, NetworkNodeManager and StorageDiskManager * fixed formatting and misc * remove more random newlines * 1.16 and implement requested changes * remove world parameter from getStorageDiskManager * Fix load order issue * remove unused worldKey * fix requested changes * fix more requested changes * remove getCause(). * fix formatting more --- .../refinedstorage/api/IRSAPI.java | 3 +- .../refinedstorage/apiimpl/API.java | 12 +- .../apiimpl/network/NetworkManager.java | 35 +++-- .../apiimpl/network/NetworkNodeManager.java | 36 +++-- .../node/diskdrive/DiskDriveNetworkNode.java | 1 - .../DiskManipulatorNetworkNode.java | 2 - .../node/storage/FluidStorageNetworkNode.java | 6 +- .../node/storage/StorageNetworkNode.java | 6 +- .../storage/disk/FluidStorageDisk.java | 2 +- .../apiimpl/storage/disk/ItemStorageDisk.java | 2 +- .../storage/disk/StorageDiskManager.java | 36 +++-- .../item/FluidStorageDiskItem.java | 10 +- .../refinedstorage/item/StorageDiskItem.java | 10 +- .../item/blockitem/FluidStorageBlockItem.java | 6 +- .../item/blockitem/StorageBlockItem.java | 6 +- .../disk/StorageDiskSizeRequestMessage.java | 2 +- .../refinedstorage/setup/CommonSetup.java | 11 ++ .../refinedstorage/setup/ServerSetup.java | 27 ++++ .../tile/grid/portable/PortableGrid.java | 2 +- .../tile/grid/portable/PortableGridTile.java | 2 +- .../refinedstorage/util/ISaveData.java | 36 +++++ .../refinedstorage/util/SaveDataManager.java | 129 ++++++++++++++++++ .../refinedstorage/util/StackUtils.java | 4 +- 23 files changed, 305 insertions(+), 81 deletions(-) create mode 100644 src/main/java/com/refinedmods/refinedstorage/util/ISaveData.java create mode 100644 src/main/java/com/refinedmods/refinedstorage/util/SaveDataManager.java diff --git a/src/main/java/com/refinedmods/refinedstorage/api/IRSAPI.java b/src/main/java/com/refinedmods/refinedstorage/api/IRSAPI.java index 3822da857..21d1a07c8 100644 --- a/src/main/java/com/refinedmods/refinedstorage/api/IRSAPI.java +++ b/src/main/java/com/refinedmods/refinedstorage/api/IRSAPI.java @@ -125,11 +125,10 @@ public interface IRSAPI { IStorageDiskRegistry getStorageDiskRegistry(); /** - * @param anyWorld any world associated with the server * @return the storage disk manager */ @Nonnull - IStorageDiskManager getStorageDiskManager(ServerWorld anyWorld); + IStorageDiskManager getStorageDiskManager(); /** * @return the storage disk sync manager diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/API.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/API.java index ae6fa7e51..fec2fafc4 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/API.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/API.java @@ -39,10 +39,12 @@ import com.refinedmods.refinedstorage.apiimpl.util.Comparer; import com.refinedmods.refinedstorage.apiimpl.util.FluidStackList; import com.refinedmods.refinedstorage.apiimpl.util.ItemStackList; import com.refinedmods.refinedstorage.apiimpl.util.QuantityFormatter; +import com.refinedmods.refinedstorage.util.SaveDataManager; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.INBT; import net.minecraft.nbt.ListNBT; +import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.ModList; @@ -125,12 +127,12 @@ public class API implements IRSAPI { @Override public INetworkNodeManager getNetworkNodeManager(ServerWorld world) { - return world.getSavedData().getOrCreate(() -> new NetworkNodeManager("network_nodes", world), "network_nodes"); + return SaveDataManager.INSTANCE.getManager(NetworkNodeManager.class, world.func_234923_W_()); } @Override public INetworkManager getNetworkManager(ServerWorld world) { - return world.getSavedData().getOrCreate(() -> new NetworkManager("networks", world), "networks"); + return SaveDataManager.INSTANCE.getManager(NetworkManager.class, world.func_234923_W_()); } @Override @@ -189,10 +191,8 @@ public class API implements IRSAPI { @Nonnull @Override - public IStorageDiskManager getStorageDiskManager(ServerWorld anyWorld) { - ServerWorld world = anyWorld.getServer().func_241755_D_(); // Get the overworld - - return world.getSavedData().getOrCreate(() -> new StorageDiskManager(StorageDiskManager.NAME, world), StorageDiskManager.NAME); + public IStorageDiskManager getStorageDiskManager() { + return SaveDataManager.INSTANCE.getManager(StorageDiskManager.class, World.field_234918_g_); } @Nonnull diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkManager.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkManager.java index ec59ce8dc..411b8c023 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkManager.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkManager.java @@ -3,11 +3,13 @@ package com.refinedmods.refinedstorage.apiimpl.network; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkManager; import com.refinedmods.refinedstorage.api.network.NetworkType; +import com.refinedmods.refinedstorage.util.ISaveData; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; +import net.minecraft.util.RegistryKey; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraft.world.storage.WorldSavedData; +import net.minecraft.world.server.ServerWorld; import net.minecraftforge.common.util.Constants; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -16,7 +18,7 @@ import javax.annotation.Nullable; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; -public class NetworkManager extends WorldSavedData implements INetworkManager { +public class NetworkManager implements INetworkManager, ISaveData { public static final String NAME = "refinedstorage_networks"; private static final String NBT_NETWORKS = "Networks"; @@ -24,20 +26,14 @@ public class NetworkManager extends WorldSavedData implements INetworkManager { private static final String NBT_DATA = "Data"; private static final String NBT_POS = "Pos"; - private final World world; + private boolean dirty; private final Logger logger = LogManager.getLogger(getClass()); private final ConcurrentHashMap networks = new ConcurrentHashMap<>(); - public NetworkManager(String name, World world) { - super(name); - - this.world = world; - } - @Override - public void read(CompoundNBT tag) { + public void read(CompoundNBT tag, ServerWorld world) { if (tag.contains(NBT_NETWORKS)) { ListNBT networksTag = tag.getList(NBT_NETWORKS, Constants.NBT.TAG_COMPOUND); @@ -64,7 +60,12 @@ public class NetworkManager extends WorldSavedData implements INetworkManager { } @Override - public CompoundNBT write(CompoundNBT tag) { + public String getName() { + return NAME; + } + + @Override + public void write(CompoundNBT tag) { ListNBT list = new ListNBT(); for (INetwork network : all()) { @@ -82,8 +83,16 @@ public class NetworkManager extends WorldSavedData implements INetworkManager { } tag.put(NBT_NETWORKS, list); + } - return tag; + @Override + public boolean isMarkedForSaving() { + return dirty; + } + + @Override + public void markSaved() { + dirty = false; } @Nullable @@ -121,6 +130,6 @@ public class NetworkManager extends WorldSavedData implements INetworkManager { @Override public void markForSaving() { - markDirty(); + dirty = true; } } diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeManager.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeManager.java index 3c26bab9d..70d28b3f3 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeManager.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeManager.java @@ -4,12 +4,12 @@ import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeFactory; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager; import com.refinedmods.refinedstorage.apiimpl.API; +import com.refinedmods.refinedstorage.util.ISaveData; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.storage.WorldSavedData; +import net.minecraft.world.server.ServerWorld; import net.minecraftforge.common.util.Constants; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -18,7 +18,7 @@ import javax.annotation.Nullable; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; -public class NetworkNodeManager extends WorldSavedData implements INetworkNodeManager { +public class NetworkNodeManager implements INetworkNodeManager, ISaveData { public static final String NAME = "refinedstorage_nodes"; private static final String NBT_NODES = "Nodes"; @@ -26,20 +26,14 @@ public class NetworkNodeManager extends WorldSavedData implements INetworkNodeMa private static final String NBT_NODE_DATA = "Data"; private static final String NBT_NODE_POS = "Pos"; - private final World world; + private boolean dirty; private final Logger logger = LogManager.getLogger(getClass()); private final ConcurrentHashMap nodes = new ConcurrentHashMap<>(); - public NetworkNodeManager(String name, World world) { - super(name); - - this.world = world; - } - @Override - public void read(CompoundNBT tag) { + public void read(CompoundNBT tag, ServerWorld world) { if (tag.contains(NBT_NODES)) { ListNBT nodesTag = tag.getList(NBT_NODES, Constants.NBT.TAG_COMPOUND); @@ -74,7 +68,22 @@ public class NetworkNodeManager extends WorldSavedData implements INetworkNodeMa } @Override - public CompoundNBT write(CompoundNBT tag) { + public boolean isMarkedForSaving() { + return dirty; + } + + @Override + public void markSaved() { + dirty = false; + } + + @Override + public String getName() { + return NAME; + } + + @Override + public void write(CompoundNBT tag) { ListNBT list = new ListNBT(); for (INetworkNode node : all()) { @@ -93,7 +102,6 @@ public class NetworkNodeManager extends WorldSavedData implements INetworkNodeMa tag.put(NBT_NODES, list); - return tag; } @Nullable @@ -131,6 +139,6 @@ public class NetworkNodeManager extends WorldSavedData implements INetworkNodeMa @Override public void markForSaving() { - markDirty(); + dirty = true; } } diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/DiskDriveNetworkNode.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/DiskDriveNetworkNode.java index fd0dfe7d5..b781d9561 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/DiskDriveNetworkNode.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/DiskDriveNetworkNode.java @@ -66,7 +66,6 @@ public class DiskDriveNetworkNode extends NetworkNode implements IStorageProvide .addListener((handler, slot, reading) -> { if (!world.isRemote) { StackUtils.createStorages( - (ServerWorld) world, handler.getStackInSlot(slot), slot, itemDisks, diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/DiskManipulatorNetworkNode.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/DiskManipulatorNetworkNode.java index bc1153d2d..bbd14a0a3 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/DiskManipulatorNetworkNode.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/DiskManipulatorNetworkNode.java @@ -78,7 +78,6 @@ public class DiskManipulatorNetworkNode extends NetworkNode implements IComparab .addListener((handler, slot, reading) -> { if (!world.isRemote) { StackUtils.createStorages( - (ServerWorld) world, handler.getStackInSlot(slot), slot, itemDisks, @@ -99,7 +98,6 @@ public class DiskManipulatorNetworkNode extends NetworkNode implements IComparab .addListener(((handler, slot, reading) -> { if (!world.isRemote) { StackUtils.createStorages( - (ServerWorld) world, handler.getStackInSlot(slot), 3 + slot, itemDisks, diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/FluidStorageNetworkNode.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/FluidStorageNetworkNode.java index f61b5fc58..d7981948d 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/FluidStorageNetworkNode.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/FluidStorageNetworkNode.java @@ -139,11 +139,11 @@ public class FluidStorageNetworkNode extends NetworkNode implements IStorageScre } public void loadStorage() { - IStorageDisk disk = API.instance().getStorageDiskManager((ServerWorld) world).get(storageId); + IStorageDisk disk = API.instance().getStorageDiskManager().get(storageId); if (disk == null) { - API.instance().getStorageDiskManager((ServerWorld) world).set(storageId, disk = API.instance().createDefaultFluidDisk((ServerWorld) world, type.getCapacity())); - API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); + API.instance().getStorageDiskManager().set(storageId, disk = API.instance().createDefaultFluidDisk((ServerWorld) world, type.getCapacity())); + API.instance().getStorageDiskManager().markForSaving(); } this.storage = new FluidStorageWrapperStorageDisk(this, disk); diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/StorageNetworkNode.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/StorageNetworkNode.java index 235493000..8268e9f5d 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/StorageNetworkNode.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/StorageNetworkNode.java @@ -139,11 +139,11 @@ public class StorageNetworkNode extends NetworkNode implements IStorageScreen, I } public void loadStorage() { - IStorageDisk disk = API.instance().getStorageDiskManager((ServerWorld) world).get(storageId); + IStorageDisk disk = API.instance().getStorageDiskManager().get(storageId); if (disk == null) { - API.instance().getStorageDiskManager((ServerWorld) world).set(storageId, disk = API.instance().createDefaultItemDisk((ServerWorld) world, type.getCapacity())); - API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); + API.instance().getStorageDiskManager().set(storageId, disk = API.instance().createDefaultItemDisk((ServerWorld) world, type.getCapacity())); + API.instance().getStorageDiskManager().markForSaving(); } this.storage = new ItemStorageWrapperStorageDisk(this, disk); diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/FluidStorageDisk.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/FluidStorageDisk.java index a95aeec31..b94ee1cd7 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/FluidStorageDisk.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/FluidStorageDisk.java @@ -203,7 +203,7 @@ public class FluidStorageDisk implements IStorageDisk { } if (world != null) { - API.instance().getStorageDiskManager(world).markForSaving(); + API.instance().getStorageDiskManager().markForSaving(); } } } diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/ItemStorageDisk.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/ItemStorageDisk.java index a0bf5cc6e..3db1b7f64 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/ItemStorageDisk.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/ItemStorageDisk.java @@ -204,7 +204,7 @@ public class ItemStorageDisk implements IStorageDisk { } if (world != null) { - API.instance().getStorageDiskManager(world).markForSaving(); + API.instance().getStorageDiskManager().markForSaving(); } } } \ No newline at end of file diff --git a/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskManager.java b/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskManager.java index 334d6b09a..469b09b0f 100644 --- a/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskManager.java +++ b/src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskManager.java @@ -5,12 +5,12 @@ import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskManager; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.refinedmods.refinedstorage.apiimpl.API; +import com.refinedmods.refinedstorage.util.ISaveData; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.util.ResourceLocation; import net.minecraft.world.server.ServerWorld; -import net.minecraft.world.storage.WorldSavedData; import net.minecraftforge.common.util.Constants; import javax.annotation.Nullable; @@ -18,7 +18,7 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -public class StorageDiskManager extends WorldSavedData implements IStorageDiskManager { +public class StorageDiskManager implements IStorageDiskManager, ISaveData { public static final String NAME = "refinedstorage_disks"; private static final String NBT_DISKS = "Disks"; @@ -27,13 +27,9 @@ public class StorageDiskManager extends WorldSavedData implements IStorageDiskMa private static final String NBT_DISK_DATA = "Data"; private final Map disks = new HashMap<>(); - private final ServerWorld world; - public StorageDiskManager(String name, ServerWorld world) { - super(name); + private boolean dirty; - this.world = world; - } @Override @Nullable @@ -90,13 +86,13 @@ public class StorageDiskManager extends WorldSavedData implements IStorageDiskMa @Override public void markForSaving() { - markDirty(); + dirty = true; } @Override - public void read(CompoundNBT tag) { - if (tag.contains(NBT_DISKS)) { - ListNBT disksTag = tag.getList(NBT_DISKS, Constants.NBT.TAG_COMPOUND); + public void read(CompoundNBT nbt, ServerWorld world) { + if (nbt.contains(NBT_DISKS)) { + ListNBT disksTag = nbt.getList(NBT_DISKS, Constants.NBT.TAG_COMPOUND); for (int i = 0; i < disksTag.size(); ++i) { CompoundNBT diskTag = disksTag.getCompound(i); @@ -114,7 +110,7 @@ public class StorageDiskManager extends WorldSavedData implements IStorageDiskMa } @Override - public CompoundNBT write(CompoundNBT tag) { + public void write(CompoundNBT nbt) { ListNBT disks = new ListNBT(); for (Map.Entry entry : this.disks.entrySet()) { @@ -126,9 +122,21 @@ public class StorageDiskManager extends WorldSavedData implements IStorageDiskMa disks.add(diskTag); } + nbt.put(NBT_DISKS, disks); + } - tag.put(NBT_DISKS, disks); + @Override + public String getName() { + return NAME; + } - return tag; + @Override + public boolean isMarkedForSaving() { + return dirty; + } + + @Override + public void markSaved() { + dirty = false; } } diff --git a/src/main/java/com/refinedmods/refinedstorage/item/FluidStorageDiskItem.java b/src/main/java/com/refinedmods/refinedstorage/item/FluidStorageDiskItem.java index 6f1d33f5e..6c5a360fa 100644 --- a/src/main/java/com/refinedmods/refinedstorage/item/FluidStorageDiskItem.java +++ b/src/main/java/com/refinedmods/refinedstorage/item/FluidStorageDiskItem.java @@ -49,8 +49,8 @@ public class FluidStorageDiskItem extends Item implements IStorageDiskProvider { if (!world.isRemote && !stack.hasTag()) { UUID id = UUID.randomUUID(); - API.instance().getStorageDiskManager((ServerWorld) world).set(id, API.instance().createDefaultFluidDisk((ServerWorld) world, getCapacity(stack))); - API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); + API.instance().getStorageDiskManager().set(id, API.instance().createDefaultFluidDisk((ServerWorld) world, getCapacity(stack))); + API.instance().getStorageDiskManager().markForSaving(); setId(stack, id); } @@ -85,7 +85,7 @@ public class FluidStorageDiskItem extends Item implements IStorageDiskProvider { ItemStack diskStack = player.getHeldItem(hand); if (!world.isRemote && player.isCrouching() && type != FluidStorageType.CREATIVE) { - IStorageDisk disk = API.instance().getStorageDiskManager((ServerWorld) world).getByStack(diskStack); + IStorageDisk disk = API.instance().getStorageDiskManager().getByStack(diskStack); if (disk != null && disk.getStored() == 0) { ItemStack storagePart = new ItemStack(FluidStoragePartItem.getByType(type), diskStack.getCount()); @@ -94,8 +94,8 @@ public class FluidStorageDiskItem extends Item implements IStorageDiskProvider { InventoryHelper.spawnItemStack(world, player.getPosX(), player.getPosY(), player.getPosZ(), storagePart); } - API.instance().getStorageDiskManager((ServerWorld) world).remove(getId(diskStack)); - API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); + API.instance().getStorageDiskManager().remove(getId(diskStack)); + API.instance().getStorageDiskManager().markForSaving(); return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING)); } diff --git a/src/main/java/com/refinedmods/refinedstorage/item/StorageDiskItem.java b/src/main/java/com/refinedmods/refinedstorage/item/StorageDiskItem.java index b159df426..85371d0dc 100644 --- a/src/main/java/com/refinedmods/refinedstorage/item/StorageDiskItem.java +++ b/src/main/java/com/refinedmods/refinedstorage/item/StorageDiskItem.java @@ -49,8 +49,8 @@ public class StorageDiskItem extends Item implements IStorageDiskProvider { if (!world.isRemote && !stack.hasTag()) { UUID id = UUID.randomUUID(); - API.instance().getStorageDiskManager((ServerWorld) world).set(id, API.instance().createDefaultItemDisk((ServerWorld) world, getCapacity(stack))); - API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); + API.instance().getStorageDiskManager().set(id, API.instance().createDefaultItemDisk((ServerWorld) world, getCapacity(stack))); + API.instance().getStorageDiskManager().markForSaving(); setId(stack, id); } @@ -85,7 +85,7 @@ public class StorageDiskItem extends Item implements IStorageDiskProvider { ItemStack diskStack = player.getHeldItem(hand); if (!world.isRemote && player.isCrouching() && type != ItemStorageType.CREATIVE) { - IStorageDisk disk = API.instance().getStorageDiskManager((ServerWorld) world).getByStack(diskStack); + IStorageDisk disk = API.instance().getStorageDiskManager().getByStack(diskStack); if (disk != null && disk.getStored() == 0) { ItemStack storagePart = new ItemStack(StoragePartItem.getByType(type), diskStack.getCount()); @@ -94,8 +94,8 @@ public class StorageDiskItem extends Item implements IStorageDiskProvider { InventoryHelper.spawnItemStack(world, player.getPosX(), player.getPosY(), player.getPosZ(), storagePart); } - API.instance().getStorageDiskManager((ServerWorld) world).remove(getId(diskStack)); - API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); + API.instance().getStorageDiskManager().remove(getId(diskStack)); + API.instance().getStorageDiskManager().markForSaving(); return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING)); } diff --git a/src/main/java/com/refinedmods/refinedstorage/item/blockitem/FluidStorageBlockItem.java b/src/main/java/com/refinedmods/refinedstorage/item/blockitem/FluidStorageBlockItem.java index 98862502a..5accfa959 100644 --- a/src/main/java/com/refinedmods/refinedstorage/item/blockitem/FluidStorageBlockItem.java +++ b/src/main/java/com/refinedmods/refinedstorage/item/blockitem/FluidStorageBlockItem.java @@ -75,7 +75,7 @@ public class FluidStorageBlockItem extends BaseBlockItem { if (isValid(storageStack)) { diskId = getId(storageStack); - disk = API.instance().getStorageDiskManager((ServerWorld) world).get(diskId); + disk = API.instance().getStorageDiskManager().get(diskId); } // Newly created fluid storages won't have a tag yet, so allow invalid disks as well. @@ -99,8 +99,8 @@ public class FluidStorageBlockItem extends BaseBlockItem { } if (disk != null) { - API.instance().getStorageDiskManager((ServerWorld) world).remove(diskId); - API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); + API.instance().getStorageDiskManager().remove(diskId); + API.instance().getStorageDiskManager().markForSaving(); } return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSBlocks.MACHINE_CASING)); diff --git a/src/main/java/com/refinedmods/refinedstorage/item/blockitem/StorageBlockItem.java b/src/main/java/com/refinedmods/refinedstorage/item/blockitem/StorageBlockItem.java index 53927ca14..b40b1485e 100644 --- a/src/main/java/com/refinedmods/refinedstorage/item/blockitem/StorageBlockItem.java +++ b/src/main/java/com/refinedmods/refinedstorage/item/blockitem/StorageBlockItem.java @@ -73,7 +73,7 @@ public class StorageBlockItem extends BaseBlockItem { if (isValid(storageStack)) { diskId = getId(storageStack); - disk = API.instance().getStorageDiskManager((ServerWorld) world).get(diskId); + disk = API.instance().getStorageDiskManager().get(diskId); } // Newly created storages won't have a tag yet, so allow invalid disks as well. @@ -85,8 +85,8 @@ public class StorageBlockItem extends BaseBlockItem { } if (disk != null) { - API.instance().getStorageDiskManager((ServerWorld) world).remove(diskId); - API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); + API.instance().getStorageDiskManager().remove(diskId); + API.instance().getStorageDiskManager().markForSaving(); } return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSBlocks.MACHINE_CASING)); diff --git a/src/main/java/com/refinedmods/refinedstorage/network/disk/StorageDiskSizeRequestMessage.java b/src/main/java/com/refinedmods/refinedstorage/network/disk/StorageDiskSizeRequestMessage.java index 83bef0928..0f7d8efc7 100644 --- a/src/main/java/com/refinedmods/refinedstorage/network/disk/StorageDiskSizeRequestMessage.java +++ b/src/main/java/com/refinedmods/refinedstorage/network/disk/StorageDiskSizeRequestMessage.java @@ -26,7 +26,7 @@ public class StorageDiskSizeRequestMessage { public static void handle(StorageDiskSizeRequestMessage message, Supplier ctx) { ctx.get().enqueueWork(() -> { - IStorageDisk disk = API.instance().getStorageDiskManager(ctx.get().getSender().getServerWorld()).get(message.id); + IStorageDisk disk = API.instance().getStorageDiskManager().get(message.id); if (disk != null) { RS.NETWORK_HANDLER.sendTo(ctx.get().getSender(), new StorageDiskSizeResponseMessage(message.id, disk.getStored(), disk.getCapacity())); diff --git a/src/main/java/com/refinedmods/refinedstorage/setup/CommonSetup.java b/src/main/java/com/refinedmods/refinedstorage/setup/CommonSetup.java index 7c2a42d43..02267dfaf 100644 --- a/src/main/java/com/refinedmods/refinedstorage/setup/CommonSetup.java +++ b/src/main/java/com/refinedmods/refinedstorage/setup/CommonSetup.java @@ -16,7 +16,9 @@ import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.FluidCrafting import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ItemCraftingPreviewElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory; import com.refinedmods.refinedstorage.apiimpl.network.NetworkListener; +import com.refinedmods.refinedstorage.apiimpl.network.NetworkManager; import com.refinedmods.refinedstorage.apiimpl.network.NetworkNodeListener; +import com.refinedmods.refinedstorage.apiimpl.network.NetworkNodeManager; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.*; import com.refinedmods.refinedstorage.apiimpl.network.node.*; import com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive.DiskDriveNetworkNode; @@ -25,6 +27,7 @@ import com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageN import com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; +import com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskManager; import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.FluidStorageDiskFactory; import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.ItemStorageDiskFactory; import com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.FluidExternalStorageProvider; @@ -44,6 +47,7 @@ import com.refinedmods.refinedstorage.tile.data.TileDataManager; import com.refinedmods.refinedstorage.tile.grid.GridTile; import com.refinedmods.refinedstorage.tile.grid.portable.PortableGridTile; import com.refinedmods.refinedstorage.util.BlockUtils; +import com.refinedmods.refinedstorage.util.SaveDataManager; import net.minecraft.block.Block; import net.minecraft.inventory.container.ContainerType; import net.minecraft.item.Item; @@ -51,6 +55,8 @@ import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.RegistryKey; +import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.extensions.IForgeContainerType; import net.minecraftforge.event.RegistryEvent; @@ -137,6 +143,11 @@ public class CommonSetup { if (InventorySorterIntegration.isLoaded()) { InventorySorterIntegration.register(); } + + //The StorageDiskManager needs to be loaded before the Network! + SaveDataManager.INSTANCE.registerManager(StorageDiskManager.class, StorageDiskManager::new); + SaveDataManager.INSTANCE.registerManager(NetworkNodeManager.class, NetworkNodeManager::new); + SaveDataManager.INSTANCE.registerManager(NetworkManager.class, NetworkManager::new); } private INetworkNode readAndReturn(CompoundNBT tag, NetworkNode node) { diff --git a/src/main/java/com/refinedmods/refinedstorage/setup/ServerSetup.java b/src/main/java/com/refinedmods/refinedstorage/setup/ServerSetup.java index 4ddd7da10..adf9d51e4 100644 --- a/src/main/java/com/refinedmods/refinedstorage/setup/ServerSetup.java +++ b/src/main/java/com/refinedmods/refinedstorage/setup/ServerSetup.java @@ -1,7 +1,11 @@ package com.refinedmods.refinedstorage.setup; import com.refinedmods.refinedstorage.command.PatternDumpCommand; +import com.refinedmods.refinedstorage.util.SaveDataManager; import net.minecraft.command.Commands; +import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent; @@ -13,4 +17,27 @@ public class ServerSetup { .then(PatternDumpCommand.register(e.getCommandDispatcher())) ); } + + @SubscribeEvent + public void onWorldSave(WorldEvent.Save e) { + if (!e.getWorld().isRemote()) { + SaveDataManager.INSTANCE.save((ServerWorld) e.getWorld()); + } + } + + @SubscribeEvent + public void onWorldLoad(WorldEvent.Load e) { + if (!e.getWorld().isRemote()) { + SaveDataManager.INSTANCE.read((ServerWorld) e.getWorld()); + } + } + + @SubscribeEvent + public void onWorldUnload(WorldEvent.Unload e) { + //Overworld is the only dimension that only gets unloaded when the save game is switched + //Other dimensions may get unloaded at any point + if (!e.getWorld().isRemote()) { + SaveDataManager.INSTANCE.removeManagers((ServerWorld) e.getWorld()); + } + } } diff --git a/src/main/java/com/refinedmods/refinedstorage/tile/grid/portable/PortableGrid.java b/src/main/java/com/refinedmods/refinedstorage/tile/grid/portable/PortableGrid.java index c07f1860e..d3c31cccf 100644 --- a/src/main/java/com/refinedmods/refinedstorage/tile/grid/portable/PortableGrid.java +++ b/src/main/java/com/refinedmods/refinedstorage/tile/grid/portable/PortableGrid.java @@ -107,7 +107,7 @@ public class PortableGrid implements IGrid, IPortableGrid, IStorageDiskContainer storage = null; cache = null; } else { - IStorageDisk disk = API.instance().getStorageDiskManager((ServerWorld) player.world).getByStack(getDisk().getStackInSlot(0)); + IStorageDisk disk = API.instance().getStorageDiskManager().getByStack(getDisk().getStackInSlot(0)); if (disk != null) { StorageType type = ((IStorageDiskProvider) getDisk().getStackInSlot(0).getItem()).getType(); diff --git a/src/main/java/com/refinedmods/refinedstorage/tile/grid/portable/PortableGridTile.java b/src/main/java/com/refinedmods/refinedstorage/tile/grid/portable/PortableGridTile.java index 242852924..4cfb0fabd 100644 --- a/src/main/java/com/refinedmods/refinedstorage/tile/grid/portable/PortableGridTile.java +++ b/src/main/java/com/refinedmods/refinedstorage/tile/grid/portable/PortableGridTile.java @@ -190,7 +190,7 @@ public class PortableGridTile extends BaseTile implements IGrid, IPortableGrid, this.storage = null; this.cache = null; } else { - IStorageDisk disk = API.instance().getStorageDiskManager((ServerWorld) world).getByStack(getDisk().getStackInSlot(0)); + IStorageDisk disk = API.instance().getStorageDiskManager().getByStack(getDisk().getStackInSlot(0)); if (disk != null) { StorageType type = ((IStorageDiskProvider) getDisk().getStackInSlot(0).getItem()).getType(); diff --git a/src/main/java/com/refinedmods/refinedstorage/util/ISaveData.java b/src/main/java/com/refinedmods/refinedstorage/util/ISaveData.java new file mode 100644 index 000000000..7e85b4485 --- /dev/null +++ b/src/main/java/com/refinedmods/refinedstorage/util/ISaveData.java @@ -0,0 +1,36 @@ +package com.refinedmods.refinedstorage.util; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.RegistryKey; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; + +public interface ISaveData { + /** + * @return file name + */ + String getName(); + + /** + * @param nbt tag to write data to + */ + void write(CompoundNBT nbt); + + /** + * @param nbt tag to read data from + * @param world that the data is being loaded for + */ + void read(CompoundNBT nbt, ServerWorld world); + + /** + * Does this file need to be saved? + * + * @return isDirty + */ + boolean isMarkedForSaving(); + + /** + * mark file as not in need of saving + */ + void markSaved(); +} diff --git a/src/main/java/com/refinedmods/refinedstorage/util/SaveDataManager.java b/src/main/java/com/refinedmods/refinedstorage/util/SaveDataManager.java new file mode 100644 index 000000000..106eb6f6a --- /dev/null +++ b/src/main/java/com/refinedmods/refinedstorage/util/SaveDataManager.java @@ -0,0 +1,129 @@ +package com.refinedmods.refinedstorage.util; + +import com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskManager; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.util.RegistryKey; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.storage.FolderName; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Supplier; + +public class SaveDataManager { + public static final SaveDataManager INSTANCE = new SaveDataManager(); + + private static final Logger LOGGER = LogManager.getLogger(SaveDataManager.class); + + private final Map, Map, ISaveData>> worldSaveData = new HashMap<>(); + private final LinkedHashMap, Supplier> managerTypes = new LinkedHashMap<>(); + + public void registerManager(Class clazz, Supplier supplier) { + managerTypes.put(clazz, supplier); + } + + private void createManagers(RegistryKey worldKey) { + Map, ISaveData> map = new LinkedHashMap<>(); + managerTypes.forEach((clazz, supplier) -> { + if (clazz == StorageDiskManager.class) { + if (worldKey == World.field_234918_g_) { + map.put(clazz, supplier.get()); + } + } else { + map.put(clazz, supplier.get()); + } + }); + worldSaveData.put(worldKey, map); + } + + public T getManager(Class clazz, RegistryKey worldKey) { + return clazz.cast(worldSaveData.get(worldKey).get(clazz)); + } + + public void removeManagers(ServerWorld world) { + worldSaveData.remove(world.func_234923_W_()); + } + + public void read(ServerWorld world) { + RegistryKey worldKey = world.func_234923_W_(); + if (!worldSaveData.containsKey(worldKey)) { + createManagers(worldKey); + } + + for (ISaveData saveData : worldSaveData.get(worldKey).values()) { + CompoundNBT nbt = readTagFromFile(world, saveData.getName()); + saveData.read(nbt, world); + } + } + + public void save(ServerWorld world) { + for (ISaveData saveData : worldSaveData.get(world.func_234923_W_()).values()) { + if (saveData.isMarkedForSaving()) { + CompoundNBT nbt = new CompoundNBT(); + saveData.write(nbt); + try { + writeTagToFile(world, saveData.getName(), nbt); + } catch (IOException e) { + LOGGER.error("Unable to save " + saveData.getName(), e); + + } + } + saveData.markSaved(); + } + } + + private void writeTagToFile(ServerWorld world, String fileName, CompoundNBT nbt) throws IOException { + String dataDirectory = world.getServer().func_240776_a_(new FolderName("data")).toString(); + File backupFile = new File(dataDirectory, fileName + "_backup.dat"); + File file = new File(dataDirectory, fileName + ".dat"); + + if (backupFile.exists()) { + backupFile.delete(); + } + CompressedStreamTools.writeCompressed(nbt, new FileOutputStream(backupFile)); + if (file.exists()) { + if (!file.delete()) { + throw new IOException("Cannot delete " + file.getAbsolutePath() + " aborting"); + } + } + backupFile.renameTo(file); + } + + private CompoundNBT readTagFromFile(ServerWorld world, String fileName) { + String dataDirectory = world.getServer().func_240776_a_(new FolderName("data")).toString(); + File backupFile = new File(dataDirectory, fileName + "_backup.dat"); + File file = new File(dataDirectory, fileName + ".dat"); + + CompoundNBT nbt = null; + if (file.exists()) { + try { + nbt = CompressedStreamTools.readCompressed(new FileInputStream(file)); + } catch (IOException e) { + LOGGER.warn("Unable to read " + fileName, e); + } + } + + if (nbt == null && backupFile.exists()) { + LOGGER.warn("Unable to read " + fileName + ", trying backup file"); + try { + nbt = CompressedStreamTools.readCompressed(new FileInputStream(backupFile)); + } catch (IOException e) { + LOGGER.warn("Unable to read " + fileName + "'s backup. Continuing without data", e); + } + } + + if (nbt == null) {// no file exists yet + return new CompoundNBT(); + } + return nbt; + } +} diff --git a/src/main/java/com/refinedmods/refinedstorage/util/StackUtils.java b/src/main/java/com/refinedmods/refinedstorage/util/StackUtils.java index 6d890931c..57bf0e27d 100644 --- a/src/main/java/com/refinedmods/refinedstorage/util/StackUtils.java +++ b/src/main/java/com/refinedmods/refinedstorage/util/StackUtils.java @@ -161,12 +161,12 @@ public final class StackUtils { } @SuppressWarnings("unchecked") - public static void createStorages(ServerWorld world, ItemStack diskStack, int slot, IStorageDisk[] itemDisks, IStorageDisk[] fluidDisks, Function, IStorageDisk> itemDiskWrapper, Function, IStorageDisk> fluidDiskWrapper) { + public static void createStorages(ItemStack diskStack, int slot, IStorageDisk[] itemDisks, IStorageDisk[] fluidDisks, Function, IStorageDisk> itemDiskWrapper, Function, IStorageDisk> fluidDiskWrapper) { if (diskStack.isEmpty()) { itemDisks[slot] = null; fluidDisks[slot] = null; } else { - IStorageDisk disk = API.instance().getStorageDiskManager(world).getByStack(diskStack); + IStorageDisk disk = API.instance().getStorageDiskManager().getByStack(diskStack); if (disk != null) { switch (((IStorageDiskProvider) diskStack.getItem()).getType()) {