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
This commit is contained in:
Darkere
2020-07-14 15:40:11 +02:00
committed by GitHub
parent f28240919e
commit 324199828d
23 changed files with 305 additions and 81 deletions

View File

@@ -125,11 +125,10 @@ public interface IRSAPI {
IStorageDiskRegistry getStorageDiskRegistry(); IStorageDiskRegistry getStorageDiskRegistry();
/** /**
* @param anyWorld any world associated with the server
* @return the storage disk manager * @return the storage disk manager
*/ */
@Nonnull @Nonnull
IStorageDiskManager getStorageDiskManager(ServerWorld anyWorld); IStorageDiskManager getStorageDiskManager();
/** /**
* @return the storage disk sync manager * @return the storage disk sync manager

View File

@@ -39,10 +39,12 @@ import com.refinedmods.refinedstorage.apiimpl.util.Comparer;
import com.refinedmods.refinedstorage.apiimpl.util.FluidStackList; import com.refinedmods.refinedstorage.apiimpl.util.FluidStackList;
import com.refinedmods.refinedstorage.apiimpl.util.ItemStackList; import com.refinedmods.refinedstorage.apiimpl.util.ItemStackList;
import com.refinedmods.refinedstorage.apiimpl.util.QuantityFormatter; import com.refinedmods.refinedstorage.apiimpl.util.QuantityFormatter;
import com.refinedmods.refinedstorage.util.SaveDataManager;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT; import net.minecraft.nbt.INBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
@@ -125,12 +127,12 @@ public class API implements IRSAPI {
@Override @Override
public INetworkNodeManager getNetworkNodeManager(ServerWorld world) { 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 @Override
public INetworkManager getNetworkManager(ServerWorld world) { 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 @Override
@@ -189,10 +191,8 @@ public class API implements IRSAPI {
@Nonnull @Nonnull
@Override @Override
public IStorageDiskManager getStorageDiskManager(ServerWorld anyWorld) { public IStorageDiskManager getStorageDiskManager() {
ServerWorld world = anyWorld.getServer().func_241755_D_(); // Get the overworld return SaveDataManager.INSTANCE.getManager(StorageDiskManager.class, World.field_234918_g_);
return world.getSavedData().getOrCreate(() -> new StorageDiskManager(StorageDiskManager.NAME, world), StorageDiskManager.NAME);
} }
@Nonnull @Nonnull

View File

@@ -3,11 +3,13 @@ package com.refinedmods.refinedstorage.apiimpl.network;
import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetwork;
import com.refinedmods.refinedstorage.api.network.INetworkManager; import com.refinedmods.refinedstorage.api.network.INetworkManager;
import com.refinedmods.refinedstorage.api.network.NetworkType; import com.refinedmods.refinedstorage.api.network.NetworkType;
import com.refinedmods.refinedstorage.util.ISaveData;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.util.RegistryKey;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.storage.WorldSavedData; import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.Constants;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -16,7 +18,7 @@ import javax.annotation.Nullable;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap; 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"; public static final String NAME = "refinedstorage_networks";
private static final String NBT_NETWORKS = "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_DATA = "Data";
private static final String NBT_POS = "Pos"; private static final String NBT_POS = "Pos";
private final World world; private boolean dirty;
private final Logger logger = LogManager.getLogger(getClass()); private final Logger logger = LogManager.getLogger(getClass());
private final ConcurrentHashMap<BlockPos, INetwork> networks = new ConcurrentHashMap<>(); private final ConcurrentHashMap<BlockPos, INetwork> networks = new ConcurrentHashMap<>();
public NetworkManager(String name, World world) {
super(name);
this.world = world;
}
@Override @Override
public void read(CompoundNBT tag) { public void read(CompoundNBT tag, ServerWorld world) {
if (tag.contains(NBT_NETWORKS)) { if (tag.contains(NBT_NETWORKS)) {
ListNBT networksTag = tag.getList(NBT_NETWORKS, Constants.NBT.TAG_COMPOUND); ListNBT networksTag = tag.getList(NBT_NETWORKS, Constants.NBT.TAG_COMPOUND);
@@ -64,7 +60,12 @@ public class NetworkManager extends WorldSavedData implements INetworkManager {
} }
@Override @Override
public CompoundNBT write(CompoundNBT tag) { public String getName() {
return NAME;
}
@Override
public void write(CompoundNBT tag) {
ListNBT list = new ListNBT(); ListNBT list = new ListNBT();
for (INetwork network : all()) { for (INetwork network : all()) {
@@ -82,8 +83,16 @@ public class NetworkManager extends WorldSavedData implements INetworkManager {
} }
tag.put(NBT_NETWORKS, list); tag.put(NBT_NETWORKS, list);
}
return tag; @Override
public boolean isMarkedForSaving() {
return dirty;
}
@Override
public void markSaved() {
dirty = false;
} }
@Nullable @Nullable
@@ -121,6 +130,6 @@ public class NetworkManager extends WorldSavedData implements INetworkManager {
@Override @Override
public void markForSaving() { public void markForSaving() {
markDirty(); dirty = true;
} }
} }

View File

@@ -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.INetworkNodeFactory;
import com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager;
import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.util.ISaveData;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.WorldSavedData;
import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.Constants;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -18,7 +18,7 @@ import javax.annotation.Nullable;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap; 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"; public static final String NAME = "refinedstorage_nodes";
private static final String NBT_NODES = "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_DATA = "Data";
private static final String NBT_NODE_POS = "Pos"; private static final String NBT_NODE_POS = "Pos";
private final World world; private boolean dirty;
private final Logger logger = LogManager.getLogger(getClass()); private final Logger logger = LogManager.getLogger(getClass());
private final ConcurrentHashMap<BlockPos, INetworkNode> nodes = new ConcurrentHashMap<>(); private final ConcurrentHashMap<BlockPos, INetworkNode> nodes = new ConcurrentHashMap<>();
public NetworkNodeManager(String name, World world) {
super(name);
this.world = world;
}
@Override @Override
public void read(CompoundNBT tag) { public void read(CompoundNBT tag, ServerWorld world) {
if (tag.contains(NBT_NODES)) { if (tag.contains(NBT_NODES)) {
ListNBT nodesTag = tag.getList(NBT_NODES, Constants.NBT.TAG_COMPOUND); ListNBT nodesTag = tag.getList(NBT_NODES, Constants.NBT.TAG_COMPOUND);
@@ -74,7 +68,22 @@ public class NetworkNodeManager extends WorldSavedData implements INetworkNodeMa
} }
@Override @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(); ListNBT list = new ListNBT();
for (INetworkNode node : all()) { for (INetworkNode node : all()) {
@@ -93,7 +102,6 @@ public class NetworkNodeManager extends WorldSavedData implements INetworkNodeMa
tag.put(NBT_NODES, list); tag.put(NBT_NODES, list);
return tag;
} }
@Nullable @Nullable
@@ -131,6 +139,6 @@ public class NetworkNodeManager extends WorldSavedData implements INetworkNodeMa
@Override @Override
public void markForSaving() { public void markForSaving() {
markDirty(); dirty = true;
} }
} }

View File

@@ -66,7 +66,6 @@ public class DiskDriveNetworkNode extends NetworkNode implements IStorageProvide
.addListener((handler, slot, reading) -> { .addListener((handler, slot, reading) -> {
if (!world.isRemote) { if (!world.isRemote) {
StackUtils.createStorages( StackUtils.createStorages(
(ServerWorld) world,
handler.getStackInSlot(slot), handler.getStackInSlot(slot),
slot, slot,
itemDisks, itemDisks,

View File

@@ -78,7 +78,6 @@ public class DiskManipulatorNetworkNode extends NetworkNode implements IComparab
.addListener((handler, slot, reading) -> { .addListener((handler, slot, reading) -> {
if (!world.isRemote) { if (!world.isRemote) {
StackUtils.createStorages( StackUtils.createStorages(
(ServerWorld) world,
handler.getStackInSlot(slot), handler.getStackInSlot(slot),
slot, slot,
itemDisks, itemDisks,
@@ -99,7 +98,6 @@ public class DiskManipulatorNetworkNode extends NetworkNode implements IComparab
.addListener(((handler, slot, reading) -> { .addListener(((handler, slot, reading) -> {
if (!world.isRemote) { if (!world.isRemote) {
StackUtils.createStorages( StackUtils.createStorages(
(ServerWorld) world,
handler.getStackInSlot(slot), handler.getStackInSlot(slot),
3 + slot, 3 + slot,
itemDisks, itemDisks,

View File

@@ -139,11 +139,11 @@ public class FluidStorageNetworkNode extends NetworkNode implements IStorageScre
} }
public void loadStorage() { public void loadStorage() {
IStorageDisk disk = API.instance().getStorageDiskManager((ServerWorld) world).get(storageId); IStorageDisk disk = API.instance().getStorageDiskManager().get(storageId);
if (disk == null) { if (disk == null) {
API.instance().getStorageDiskManager((ServerWorld) world).set(storageId, disk = API.instance().createDefaultFluidDisk((ServerWorld) world, type.getCapacity())); API.instance().getStorageDiskManager().set(storageId, disk = API.instance().createDefaultFluidDisk((ServerWorld) world, type.getCapacity()));
API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
} }
this.storage = new FluidStorageWrapperStorageDisk(this, disk); this.storage = new FluidStorageWrapperStorageDisk(this, disk);

View File

@@ -139,11 +139,11 @@ public class StorageNetworkNode extends NetworkNode implements IStorageScreen, I
} }
public void loadStorage() { public void loadStorage() {
IStorageDisk disk = API.instance().getStorageDiskManager((ServerWorld) world).get(storageId); IStorageDisk disk = API.instance().getStorageDiskManager().get(storageId);
if (disk == null) { if (disk == null) {
API.instance().getStorageDiskManager((ServerWorld) world).set(storageId, disk = API.instance().createDefaultItemDisk((ServerWorld) world, type.getCapacity())); API.instance().getStorageDiskManager().set(storageId, disk = API.instance().createDefaultItemDisk((ServerWorld) world, type.getCapacity()));
API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
} }
this.storage = new ItemStorageWrapperStorageDisk(this, disk); this.storage = new ItemStorageWrapperStorageDisk(this, disk);

View File

@@ -203,7 +203,7 @@ public class FluidStorageDisk implements IStorageDisk<FluidStack> {
} }
if (world != null) { if (world != null) {
API.instance().getStorageDiskManager(world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
} }
} }
} }

View File

@@ -204,7 +204,7 @@ public class ItemStorageDisk implements IStorageDisk<ItemStack> {
} }
if (world != null) { if (world != null) {
API.instance().getStorageDiskManager(world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
} }
} }
} }

View File

@@ -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.IStorageDiskManager;
import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider;
import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.API;
import com.refinedmods.refinedstorage.util.ISaveData;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.WorldSavedData;
import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.Constants;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -18,7 +18,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
public class StorageDiskManager extends WorldSavedData implements IStorageDiskManager { public class StorageDiskManager implements IStorageDiskManager, ISaveData {
public static final String NAME = "refinedstorage_disks"; public static final String NAME = "refinedstorage_disks";
private static final String NBT_DISKS = "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 static final String NBT_DISK_DATA = "Data";
private final Map<UUID, IStorageDisk> disks = new HashMap<>(); private final Map<UUID, IStorageDisk> disks = new HashMap<>();
private final ServerWorld world;
public StorageDiskManager(String name, ServerWorld world) { private boolean dirty;
super(name);
this.world = world;
}
@Override @Override
@Nullable @Nullable
@@ -90,13 +86,13 @@ public class StorageDiskManager extends WorldSavedData implements IStorageDiskMa
@Override @Override
public void markForSaving() { public void markForSaving() {
markDirty(); dirty = true;
} }
@Override @Override
public void read(CompoundNBT tag) { public void read(CompoundNBT nbt, ServerWorld world) {
if (tag.contains(NBT_DISKS)) { if (nbt.contains(NBT_DISKS)) {
ListNBT disksTag = tag.getList(NBT_DISKS, Constants.NBT.TAG_COMPOUND); ListNBT disksTag = nbt.getList(NBT_DISKS, Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < disksTag.size(); ++i) { for (int i = 0; i < disksTag.size(); ++i) {
CompoundNBT diskTag = disksTag.getCompound(i); CompoundNBT diskTag = disksTag.getCompound(i);
@@ -114,7 +110,7 @@ public class StorageDiskManager extends WorldSavedData implements IStorageDiskMa
} }
@Override @Override
public CompoundNBT write(CompoundNBT tag) { public void write(CompoundNBT nbt) {
ListNBT disks = new ListNBT(); ListNBT disks = new ListNBT();
for (Map.Entry<UUID, IStorageDisk> entry : this.disks.entrySet()) { for (Map.Entry<UUID, IStorageDisk> entry : this.disks.entrySet()) {
@@ -126,9 +122,21 @@ public class StorageDiskManager extends WorldSavedData implements IStorageDiskMa
disks.add(diskTag); 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;
} }
} }

View File

@@ -49,8 +49,8 @@ public class FluidStorageDiskItem extends Item implements IStorageDiskProvider {
if (!world.isRemote && !stack.hasTag()) { if (!world.isRemote && !stack.hasTag()) {
UUID id = UUID.randomUUID(); UUID id = UUID.randomUUID();
API.instance().getStorageDiskManager((ServerWorld) world).set(id, API.instance().createDefaultFluidDisk((ServerWorld) world, getCapacity(stack))); API.instance().getStorageDiskManager().set(id, API.instance().createDefaultFluidDisk((ServerWorld) world, getCapacity(stack)));
API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
setId(stack, id); setId(stack, id);
} }
@@ -85,7 +85,7 @@ public class FluidStorageDiskItem extends Item implements IStorageDiskProvider {
ItemStack diskStack = player.getHeldItem(hand); ItemStack diskStack = player.getHeldItem(hand);
if (!world.isRemote && player.isCrouching() && type != FluidStorageType.CREATIVE) { 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) { if (disk != null && disk.getStored() == 0) {
ItemStack storagePart = new ItemStack(FluidStoragePartItem.getByType(type), diskStack.getCount()); 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); InventoryHelper.spawnItemStack(world, player.getPosX(), player.getPosY(), player.getPosZ(), storagePart);
} }
API.instance().getStorageDiskManager((ServerWorld) world).remove(getId(diskStack)); API.instance().getStorageDiskManager().remove(getId(diskStack));
API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING)); return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING));
} }

View File

@@ -49,8 +49,8 @@ public class StorageDiskItem extends Item implements IStorageDiskProvider {
if (!world.isRemote && !stack.hasTag()) { if (!world.isRemote && !stack.hasTag()) {
UUID id = UUID.randomUUID(); UUID id = UUID.randomUUID();
API.instance().getStorageDiskManager((ServerWorld) world).set(id, API.instance().createDefaultItemDisk((ServerWorld) world, getCapacity(stack))); API.instance().getStorageDiskManager().set(id, API.instance().createDefaultItemDisk((ServerWorld) world, getCapacity(stack)));
API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
setId(stack, id); setId(stack, id);
} }
@@ -85,7 +85,7 @@ public class StorageDiskItem extends Item implements IStorageDiskProvider {
ItemStack diskStack = player.getHeldItem(hand); ItemStack diskStack = player.getHeldItem(hand);
if (!world.isRemote && player.isCrouching() && type != ItemStorageType.CREATIVE) { 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) { if (disk != null && disk.getStored() == 0) {
ItemStack storagePart = new ItemStack(StoragePartItem.getByType(type), diskStack.getCount()); 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); InventoryHelper.spawnItemStack(world, player.getPosX(), player.getPosY(), player.getPosZ(), storagePart);
} }
API.instance().getStorageDiskManager((ServerWorld) world).remove(getId(diskStack)); API.instance().getStorageDiskManager().remove(getId(diskStack));
API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING)); return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING));
} }

View File

@@ -75,7 +75,7 @@ public class FluidStorageBlockItem extends BaseBlockItem {
if (isValid(storageStack)) { if (isValid(storageStack)) {
diskId = getId(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. // 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) { if (disk != null) {
API.instance().getStorageDiskManager((ServerWorld) world).remove(diskId); API.instance().getStorageDiskManager().remove(diskId);
API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
} }
return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSBlocks.MACHINE_CASING)); return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSBlocks.MACHINE_CASING));

View File

@@ -73,7 +73,7 @@ public class StorageBlockItem extends BaseBlockItem {
if (isValid(storageStack)) { if (isValid(storageStack)) {
diskId = getId(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. // 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) { if (disk != null) {
API.instance().getStorageDiskManager((ServerWorld) world).remove(diskId); API.instance().getStorageDiskManager().remove(diskId);
API.instance().getStorageDiskManager((ServerWorld) world).markForSaving(); API.instance().getStorageDiskManager().markForSaving();
} }
return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSBlocks.MACHINE_CASING)); return new ActionResult<>(ActionResultType.SUCCESS, new ItemStack(RSBlocks.MACHINE_CASING));

View File

@@ -26,7 +26,7 @@ public class StorageDiskSizeRequestMessage {
public static void handle(StorageDiskSizeRequestMessage message, Supplier<NetworkEvent.Context> ctx) { public static void handle(StorageDiskSizeRequestMessage message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> { 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) { if (disk != null) {
RS.NETWORK_HANDLER.sendTo(ctx.get().getSender(), new StorageDiskSizeResponseMessage(message.id, disk.getStored(), disk.getCapacity())); RS.NETWORK_HANDLER.sendTo(ctx.get().getSender(), new StorageDiskSizeResponseMessage(message.id, disk.getStored(), disk.getCapacity()));

View File

@@ -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.preview.ItemCraftingPreviewElement;
import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory;
import com.refinedmods.refinedstorage.apiimpl.network.NetworkListener; 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.NetworkNodeListener;
import com.refinedmods.refinedstorage.apiimpl.network.NetworkNodeManager;
import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.*; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.*;
import com.refinedmods.refinedstorage.apiimpl.network.node.*; import com.refinedmods.refinedstorage.apiimpl.network.node.*;
import com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive.DiskDriveNetworkNode; 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.network.node.storage.StorageNetworkNode;
import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType;
import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; 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.FluidStorageDiskFactory;
import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.ItemStorageDiskFactory; import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.ItemStorageDiskFactory;
import com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.FluidExternalStorageProvider; 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.GridTile;
import com.refinedmods.refinedstorage.tile.grid.portable.PortableGridTile; import com.refinedmods.refinedstorage.tile.grid.portable.PortableGridTile;
import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.BlockUtils;
import com.refinedmods.refinedstorage.util.SaveDataManager;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.item.Item; import net.minecraft.item.Item;
@@ -51,6 +55,8 @@ import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.RegistryKey;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.extensions.IForgeContainerType; import net.minecraftforge.common.extensions.IForgeContainerType;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
@@ -137,6 +143,11 @@ public class CommonSetup {
if (InventorySorterIntegration.isLoaded()) { if (InventorySorterIntegration.isLoaded()) {
InventorySorterIntegration.register(); 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) { private INetworkNode readAndReturn(CompoundNBT tag, NetworkNode node) {

View File

@@ -1,7 +1,11 @@
package com.refinedmods.refinedstorage.setup; package com.refinedmods.refinedstorage.setup;
import com.refinedmods.refinedstorage.command.PatternDumpCommand; import com.refinedmods.refinedstorage.command.PatternDumpCommand;
import com.refinedmods.refinedstorage.util.SaveDataManager;
import net.minecraft.command.Commands; 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.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
@@ -13,4 +17,27 @@ public class ServerSetup {
.then(PatternDumpCommand.register(e.getCommandDispatcher())) .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());
}
}
} }

View File

@@ -107,7 +107,7 @@ public class PortableGrid implements IGrid, IPortableGrid, IStorageDiskContainer
storage = null; storage = null;
cache = null; cache = null;
} else { } 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) { if (disk != null) {
StorageType type = ((IStorageDiskProvider) getDisk().getStackInSlot(0).getItem()).getType(); StorageType type = ((IStorageDiskProvider) getDisk().getStackInSlot(0).getItem()).getType();

View File

@@ -190,7 +190,7 @@ public class PortableGridTile extends BaseTile implements IGrid, IPortableGrid,
this.storage = null; this.storage = null;
this.cache = null; this.cache = null;
} else { } else {
IStorageDisk disk = API.instance().getStorageDiskManager((ServerWorld) world).getByStack(getDisk().getStackInSlot(0)); IStorageDisk disk = API.instance().getStorageDiskManager().getByStack(getDisk().getStackInSlot(0));
if (disk != null) { if (disk != null) {
StorageType type = ((IStorageDiskProvider) getDisk().getStackInSlot(0).getItem()).getType(); StorageType type = ((IStorageDiskProvider) getDisk().getStackInSlot(0).getItem()).getType();

View File

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

View File

@@ -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<RegistryKey<World>, Map<Class<?>, ISaveData>> worldSaveData = new HashMap<>();
private final LinkedHashMap<Class<?>, Supplier<ISaveData>> managerTypes = new LinkedHashMap<>();
public void registerManager(Class<?> clazz, Supplier<ISaveData> supplier) {
managerTypes.put(clazz, supplier);
}
private void createManagers(RegistryKey<World> worldKey) {
Map<Class<?>, 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 extends ISaveData> T getManager(Class<T> clazz, RegistryKey<World> 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<World> 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;
}
}

View File

@@ -161,12 +161,12 @@ public final class StackUtils {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static void createStorages(ServerWorld world, ItemStack diskStack, int slot, IStorageDisk<ItemStack>[] itemDisks, IStorageDisk<FluidStack>[] fluidDisks, Function<IStorageDisk<ItemStack>, IStorageDisk> itemDiskWrapper, Function<IStorageDisk<FluidStack>, IStorageDisk> fluidDiskWrapper) { public static void createStorages(ItemStack diskStack, int slot, IStorageDisk<ItemStack>[] itemDisks, IStorageDisk<FluidStack>[] fluidDisks, Function<IStorageDisk<ItemStack>, IStorageDisk> itemDiskWrapper, Function<IStorageDisk<FluidStack>, IStorageDisk> fluidDiskWrapper) {
if (diskStack.isEmpty()) { if (diskStack.isEmpty()) {
itemDisks[slot] = null; itemDisks[slot] = null;
fluidDisks[slot] = null; fluidDisks[slot] = null;
} else { } else {
IStorageDisk disk = API.instance().getStorageDiskManager(world).getByStack(diskStack); IStorageDisk disk = API.instance().getStorageDiskManager().getByStack(diskStack);
if (disk != null) { if (disk != null) {
switch (((IStorageDiskProvider) diskStack.getItem()).getType()) { switch (((IStorageDiskProvider) diskStack.getItem()).getType()) {