diff --git a/src/main/java/com/minecolonies/api/colony/IColonyManager.java b/src/main/java/com/minecolonies/api/colony/IColonyManager.java index 30bac7d39a4..db641510bdb 100755 --- a/src/main/java/com/minecolonies/api/colony/IColonyManager.java +++ b/src/main/java/com/minecolonies/api/colony/IColonyManager.java @@ -3,6 +3,7 @@ import com.minecolonies.api.IMinecoloniesAPI; import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.colony.buildings.views.IBuildingView; +import com.minecolonies.api.colony.capability.IColonyManagerCapability; import com.minecolonies.api.compatibility.ICompatibilityManager; import com.minecolonies.api.crafting.IRecipeManager; import net.minecraft.core.BlockPos; @@ -269,9 +270,9 @@ static IColonyManager getInstance() void onWorldLoad(@NotNull Level world); /** - * Sets the cap for this world to loaded + * @param cap null if loaded, */ - void setCapLoaded(); + void setLoadingCap(@Nullable IColonyManagerCapability cap); /** * When a world unloads, all colonies in that world are informed. Additionally, when the last world is unloaded, delete all colonies. @@ -426,4 +427,11 @@ static IColonyManager getInstance() * @param pos the pos to open it at. */ void openReactivationWindow(final BlockPos pos); + + /** + * Adds colony directly to cap. Use only during loading! + * + * @param colony loaded colony + */ + void addColonyDirect(IColony colony, ServerLevel world); } diff --git a/src/main/java/com/minecolonies/api/colony/capability/ChunkmanagerCapability.java b/src/main/java/com/minecolonies/api/colony/capability/ChunkmanagerCapability.java index 5335f8822ba..95b7b5ec8b0 100644 --- a/src/main/java/com/minecolonies/api/colony/capability/ChunkmanagerCapability.java +++ b/src/main/java/com/minecolonies/api/colony/capability/ChunkmanagerCapability.java @@ -81,4 +81,10 @@ public Map getAllChunkStorages() { return chunkStorages; } + + @Override + public boolean isDirty() + { + return true; + } } diff --git a/src/main/java/com/minecolonies/api/colony/capability/ColonyManagerCapability.java b/src/main/java/com/minecolonies/api/colony/capability/ColonyManagerCapability.java index ecb87324822..5f1bf385f68 100644 --- a/src/main/java/com/minecolonies/api/colony/capability/ColonyManagerCapability.java +++ b/src/main/java/com/minecolonies/api/colony/capability/ColonyManagerCapability.java @@ -35,7 +35,13 @@ public class ColonyManagerCapability extends SavedData implements IColonyManager { private static final Logger LOGGER = LogUtils.getLogger(); - public static final Codec CODEC = CompoundTag.CODEC.xmap(tag -> new ColonyManagerCapability().readNBT(tag), ColonyManagerCapability::writeNBT); + public static final Codec CODEC = CompoundTag.CODEC.xmap(tag -> { + final var cap = new ColonyManagerCapability(); + IColonyManager.getInstance().setLoadingCap(cap); + cap.readNBT(tag); + IColonyManager.getInstance().setLoadingCap(null); + return cap; + }, ColonyManagerCapability::writeNBT); public static final String NAME = new ResourceLocation(Constants.MOD_ID, "colony_manager").toDebugFileName(); public static final Factory FACTORY = new Factory<>(ColonyManagerCapability::new, CodecUtil.nbtDecoder(CODEC, LOGGER, ColonyManagerCapability::new)); @@ -97,6 +103,12 @@ public int getTopID() return colonies.getTopID(); } + @Override + public boolean isDirty() + { + return true; + } + private CompoundTag writeNBT() { final CompoundTag compound = new CompoundTag(); @@ -111,16 +123,13 @@ private CompoundTag writeNBT() return compound; } - private ColonyManagerCapability readNBT(final CompoundTag compound) + private void readNBT(final CompoundTag compound) { - // Notify that we did load the cap for this world - IColonyManager.getInstance().setCapLoaded(); - if (!compound.contains(TAG_COLONIES) || !compound.contains(TAG_COLONY_MANAGER)) { BackUpHelper.loadMissingColonies(); BackUpHelper.loadManagerBackup(); - return this; + return; } // Load all colonies from Nbt @@ -159,7 +168,7 @@ private ColonyManagerCapability readNBT(final CompoundTag compound) } freshLoaded = compound; - return this; + return; } void processAfterLoadHook(final boolean overworld) diff --git a/src/main/java/com/minecolonies/api/colony/capability/ColonyTagCapability.java b/src/main/java/com/minecolonies/api/colony/capability/ColonyTagCapability.java index 4f715d42611..820064aeef5 100644 --- a/src/main/java/com/minecolonies/api/colony/capability/ColonyTagCapability.java +++ b/src/main/java/com/minecolonies/api/colony/capability/ColonyTagCapability.java @@ -2,6 +2,7 @@ import com.minecolonies.api.colony.IColony; import com.minecolonies.api.colony.IColonyManager; +import com.minecolonies.api.colony.capability.PerChunkSavedData.IDirty; import com.minecolonies.api.util.BlockPosUtil; import com.minecolonies.api.util.CodecUtil; import com.minecolonies.api.util.Log; @@ -27,7 +28,7 @@ /** * The implementation of the colonyTagCapability. */ -public class ColonyTagCapability implements IColonyTagCapability +public class ColonyTagCapability implements IColonyTagCapability, IDirty { public static final Codec CODEC = RecordCodecBuilder.create(builder -> builder .group(CodecUtil.strictOptionalField(CodecUtil.set(Codec.INT, HashSet::new), TAG_COLONIES, HashSet::new).forGetter(cap -> cap.colonies), @@ -248,4 +249,10 @@ public Map> getAllClaimingBuildings() { return claimingBuildings; } + + @Override + public boolean isDirty() + { + return true; + } } \ No newline at end of file diff --git a/src/main/java/com/minecolonies/api/colony/capability/PerChunkSavedData.java b/src/main/java/com/minecolonies/api/colony/capability/PerChunkSavedData.java index fb23881d891..1f761d9e810 100644 --- a/src/main/java/com/minecolonies/api/colony/capability/PerChunkSavedData.java +++ b/src/main/java/com/minecolonies/api/colony/capability/PerChunkSavedData.java @@ -17,7 +17,7 @@ /** * SavedData per chunk wrapper */ -public class PerChunkSavedData extends SavedData +public class PerChunkSavedData extends SavedData { /** * Actual live data @@ -34,7 +34,7 @@ public class PerChunkSavedData extends SavedData * @param codec type codec * @param logger logger for encoding/decoding errors */ - public static Factory> factory(final Supplier constructor, final Codec codec, final Logger logger) + public static Factory> factory(final Supplier constructor, final Codec codec, final Logger logger) { final Function decoder = CodecUtil.nbtDecoder(codec, logger, () -> null); final Function encoder = CodecUtil.nbtEncoder(codec, logger, () -> null); @@ -80,6 +80,12 @@ public CompoundTag save(final CompoundTag tag) return tag; } + @Override + public boolean isDirty() + { + return chunkCapabilities.values().stream().anyMatch(IDirty::isDirty); + } + public T get(final LevelChunk chunk) { return get(chunk.getPos()); @@ -89,4 +95,9 @@ public T get(final ChunkPos chunkPos) { return chunkCapabilities.computeIfAbsent(chunkPos.toLong(), key -> factory.get()); } + + public static interface IDirty + { + boolean isDirty(); + } } diff --git a/src/main/java/com/minecolonies/core/colony/ColonyManager.java b/src/main/java/com/minecolonies/core/colony/ColonyManager.java index 32210a64fe3..8fae83503fa 100755 --- a/src/main/java/com/minecolonies/core/colony/ColonyManager.java +++ b/src/main/java/com/minecolonies/core/colony/ColonyManager.java @@ -74,14 +74,26 @@ public final class ColonyManager implements IColonyManager private boolean schematicDownloaded = false; /** - * If the manager finished loading already. + * Used during cap deserialization */ - private boolean capLoaded = false; + private IColonyManagerCapability loadingColonyManagerCap; + + @Nullable + private IColonyManagerCapability getColonyManager(final ServerLevel w) + { + return loadingColonyManagerCap != null ? loadingColonyManagerCap : IColonyManagerCapability.getCapability(w); + } + + @Override + public void setLoadingCap(@Nullable final IColonyManagerCapability cap) + { + loadingColonyManagerCap = cap; + } @Override public IColony createColony(@NotNull final ServerLevel w, final BlockPos pos, @NotNull final Player player, @NotNull final String colonyName, @NotNull final String pack) { - final IColonyManagerCapability cap = IColonyManagerCapability.getCapability(w); + final IColonyManagerCapability cap = getColonyManager(w); if (cap == null) { Log.getLogger().warn(MISSING_WORLD_CAP_MESSAGE); @@ -188,7 +200,7 @@ private void deleteColony(@Nullable final IColony iColony, final boolean canDest Log.getLogger().info("Deleting colony: " + colony.getID()); - final IColonyManagerCapability cap = IColonyManagerCapability.getCapability(world); + final IColonyManagerCapability cap = getColonyManager(world); if (cap == null) { Log.getLogger().warn(MISSING_WORLD_CAP_MESSAGE); @@ -224,7 +236,7 @@ public IColony getColonyByWorld(final int id, final Level world) { return getColonyView(id, world.dimension()); } - final IColonyManagerCapability cap = IColonyManagerCapability.getCapability(serverLevel); + final IColonyManagerCapability cap = getColonyManager(serverLevel); if (cap == null) { Log.getLogger().warn(MISSING_WORLD_CAP_MESSAGE); @@ -242,7 +254,7 @@ public IColony getColonyByDimension(final int id, final ResourceKey regis { return null; } - final IColonyManagerCapability cap = IColonyManagerCapability.getCapability(world); + final IColonyManagerCapability cap = getColonyManager(world); if (cap == null) { Log.getLogger().warn(MISSING_WORLD_CAP_MESSAGE); @@ -324,7 +336,7 @@ public List getColonies(@NotNull final Level w) final ColonyList list = colonyViews.get(w.dimension()); return list == null || list.isEmpty() ? List.of() : list.getCopyAsList(); } - final IColonyManagerCapability cap = IColonyManagerCapability.getCapability(serverLevel); + final IColonyManagerCapability cap = getColonyManager(serverLevel); if (cap == null) { Log.getLogger().warn(MISSING_WORLD_CAP_MESSAGE); @@ -340,7 +352,7 @@ public List getAllColonies() final List allColonies = new ArrayList<>(); for (final ServerLevel world : net.neoforged.neoforge.server.ServerLifecycleHooks.getCurrentServer().getAllLevels()) { - final IColonyManagerCapability cap = IColonyManagerCapability.getCapability(world); + final IColonyManagerCapability cap = getColonyManager(world); if (cap != null) { allColonies.addAll(cap.getColonies()); @@ -617,14 +629,6 @@ public void onWorldLoad(@NotNull final Level w) { if (w instanceof final ServerLevel world) { - // Late-load restore if cap was not loaded - if (!capLoaded) - { - BackUpHelper.loadMissingColonies(); - BackUpHelper.loadManagerBackup(); - } - capLoaded = false; - for (@NotNull final IColony c : getColonies(world)) { c.onWorldLoad(world); @@ -634,12 +638,6 @@ public void onWorldLoad(@NotNull final Level w) } } - @Override - public void setCapLoaded() - { - this.capLoaded = true; - } - @Override public void onWorldUnload(@NotNull final Level world) { @@ -821,7 +819,7 @@ public int getTopColonyId() int top = 0; for (final ServerLevel world : ServerLifecycleHooks.getCurrentServer().getAllLevels()) { - final IColonyManagerCapability cap = IColonyManagerCapability.getCapability(world); + final IColonyManagerCapability cap = getColonyManager(world); final int tempTop = cap == null ? 0 : cap.getTopID(); if (tempTop > top) { @@ -836,4 +834,14 @@ public void resetColonyViews() { colonyViews.clear(); } + + @Override + public void addColonyDirect(final IColony colony, final ServerLevel world) + { + final IColonyManagerCapability cap = getColonyManager(world); + if (cap != null) + { + cap.addColony(colony); + } + } } diff --git a/src/main/java/com/minecolonies/core/util/BackUpHelper.java b/src/main/java/com/minecolonies/core/util/BackUpHelper.java index 5bd7b77ecdb..03061e82b7f 100755 --- a/src/main/java/com/minecolonies/core/util/BackUpHelper.java +++ b/src/main/java/com/minecolonies/core/util/BackUpHelper.java @@ -4,7 +4,6 @@ import com.minecolonies.api.colony.IColony; import com.minecolonies.api.colony.IColonyManager; import com.minecolonies.api.colony.buildings.IBuilding; -import com.minecolonies.api.colony.capability.IColonyManagerCapability; import com.minecolonies.api.util.ColonyUtils; import com.minecolonies.api.util.Log; import com.minecolonies.core.colony.Colony; @@ -476,11 +475,7 @@ public static void loadColonyBackup(final int colonyId, final ResourceKey return; } - final IColonyManagerCapability cap = IColonyManagerCapability.getCapability(colonyWorld); - if (cap != null) - { - cap.addColony(loadedColony); - } + IColonyManager.getInstance().addColonyDirect(loadedColony, colonyWorld); if (claimChunks) { diff --git a/src/main/java/com/minecolonies/core/util/ChunkDataHelper.java b/src/main/java/com/minecolonies/core/util/ChunkDataHelper.java index d13ab31fd01..2ea3203cf76 100755 --- a/src/main/java/com/minecolonies/core/util/ChunkDataHelper.java +++ b/src/main/java/com/minecolonies/core/util/ChunkDataHelper.java @@ -4,7 +4,6 @@ import com.minecolonies.api.colony.IColonyManager; import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.colony.capability.IChunkmanagerCapability; -import com.minecolonies.api.colony.capability.IColonyManagerCapability; import com.minecolonies.api.colony.capability.IColonyTagCapability; import com.minecolonies.api.util.*; import com.minecolonies.core.MineColonies; @@ -57,12 +56,6 @@ public static void loadChunk(final LevelChunk chunk, final ServerLevel world) if (!chunkManager.getAllChunkStorages().isEmpty()) { - final IColonyManagerCapability cap = IColonyManagerCapability.getCapability(world); - if (cap == null) - { - return; - } - final ChunkLoadStorage existingStorage = chunkManager.getChunkStorage(chunk.getPos().x, chunk.getPos().z); if (existingStorage != null) {