Add persistent storage for party inventories

This commit is contained in:
2025-06-11 14:33:56 +02:00
parent ee3269f504
commit 5f501a0e7e
3 changed files with 127 additions and 8 deletions
@@ -0,0 +1,101 @@
package net.krituximon.stalinium.util;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.NonNullList;
import net.minecraft.nbt.*;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.ContainerHelper;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.saveddata.SavedData;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* World-persistent store for every partys cache inventory.
* Saved/loaded automatically by the game.
*/
public class StaliniumPartyCacheData extends SavedData {
private static final String DATA_NAME = "stalinium_party_caches";
private static final int SIZE = 27;
private final Map<UUID, SimpleContainer> inventories = new HashMap<>();
/* ------------------------------------------------- */
/* helper that produces an inventory wired to setDirty */
/* ------------------------------------------------- */
private SimpleContainer newContainer() {
/* Every time the container changes, flag the data object. */
return new SimpleContainer(SIZE) {
@Override
public void setChanged() {
super.setChanged();
StaliniumPartyCacheData.this.setDirty();
}
};
}
/* ---------------- public API ---------------- */
/** Get (or lazily create) the inventory for the given party / player. */
public SimpleContainer getOrCreate(UUID id) {
return inventories.computeIfAbsent(id, __ -> newContainer());
}
/* ---------------- persistence ---------------- */
@Override
public CompoundTag save(CompoundTag tag, HolderLookup.Provider provider) {
ListTag list = new ListTag();
inventories.forEach((uuid, container) -> {
CompoundTag entry = new CompoundTag();
entry.putUUID("Id", uuid);
NonNullList<ItemStack> tmp =
NonNullList.withSize(container.getContainerSize(), ItemStack.EMPTY);
for (int i = 0; i < container.getContainerSize(); ++i) {
tmp.set(i, container.getItem(i));
}
ContainerHelper.saveAllItems(entry, tmp, provider);
list.add(entry);
});
tag.put("Inventories", list);
return tag;
}
/** Deserializer now also uses {@link #newContainer()} so the hook survives loading. */
public static StaliniumPartyCacheData load(CompoundTag tag, HolderLookup.Provider provider) {
StaliniumPartyCacheData data = new StaliniumPartyCacheData();
ListTag list = tag.getList("Inventories", Tag.TAG_COMPOUND);
list.forEach(t -> {
CompoundTag entry = (CompoundTag) t;
UUID id = entry.getUUID("Id");
SimpleContainer cont = data.newContainer();
NonNullList<ItemStack> tmp = NonNullList.withSize(SIZE, ItemStack.EMPTY);
ContainerHelper.loadAllItems(entry, tmp, provider);
for (int i = 0; i < SIZE; ++i) cont.setItem(i, tmp.get(i));
data.inventories.put(id, cont);
});
return data;
}
/* ---------------- factory / access ---------------- */
private static final SavedData.Factory<StaliniumPartyCacheData> FACTORY =
new SavedData.Factory<>(StaliniumPartyCacheData::new, StaliniumPartyCacheData::load);
public static StaliniumPartyCacheData get(Level lvl) {
if (lvl.isClientSide) throw new IllegalStateException("Called on client");
return ((ServerLevel) lvl).getDataStorage().computeIfAbsent(FACTORY, DATA_NAME);
}
}