From 6bad9163a0d48db95434f062bf2f332d66392598 Mon Sep 17 00:00:00 2001 From: Kam Date: Mon, 7 Jul 2025 05:50:29 -0400 Subject: [PATCH] Avoid saving profile on every login --- .../java/kamkeel/npcs/controllers/ProfileController.java | 8 +++++++- .../kamkeel/npcs/controllers/data/profile/Profile.java | 3 ++- src/main/java/noppes/npcs/util/CustomNPCsThreader.java | 5 +++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/kamkeel/npcs/controllers/ProfileController.java b/src/main/java/kamkeel/npcs/controllers/ProfileController.java index a8f2bf91c..77ee89578 100644 --- a/src/main/java/kamkeel/npcs/controllers/ProfileController.java +++ b/src/main/java/kamkeel/npcs/controllers/ProfileController.java @@ -97,6 +97,7 @@ public class ProfileController implements IProfileHandler { if (player == null) return; Profile profile; + boolean profileModified = false; if (activeProfiles.containsKey(player.getUniqueID())) { profile = activeProfiles.get(player.getUniqueID()); profile.player = player; @@ -109,6 +110,7 @@ public class ProfileController implements IProfileHandler { profile.getSlots().put(0, defaultSlot); profile.currentSlotId = 0; saveSlotData(player); + profileModified = true; } if (!profile.getSlots().containsKey(profile.currentSlotId)) { profile.currentSlotId = 0; @@ -117,7 +119,10 @@ public class ProfileController implements IProfileHandler { activeProfiles.put(player.getUniqueID(), profile); loadSlotData(player); verifySlotQuests(profile.player); - save(player, profile); + // Avoid saving on every login; only persist if the profile was + // modified (e.g. default slot creation). + if (profileModified) + save(player, profile); } } @@ -341,6 +346,7 @@ public class ProfileController implements IProfileHandler { return ProfileOperation.error(MSG_CANNOT_CLONE_CURRENT); } if (temporary) { + // Use a negative ID for temporary slots so they are never saved to disk. destinationSlotId = getNextAvailableTempSlot(profile); } else { if (destinationSlotId <= 0) { diff --git a/src/main/java/kamkeel/npcs/controllers/data/profile/Profile.java b/src/main/java/kamkeel/npcs/controllers/data/profile/Profile.java index 857d169f6..04ce9b66c 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/profile/Profile.java +++ b/src/main/java/kamkeel/npcs/controllers/data/profile/Profile.java @@ -81,7 +81,8 @@ public class Profile implements IProfile { compound.setInteger("CurrentSlotId", currentSlotId); NBTTagCompound slotsCompound = new NBTTagCompound(); for (Map.Entry entry : slots.entrySet()) { - // Save only non-temporary slots. + // Temporary slots (typically using negative IDs) are kept in memory + // only and skipped here so they never persist to disk. if (entry.getValue().isTemporary()) continue; slotsCompound.setTag(String.valueOf(entry.getKey()), entry.getValue().toNBT()); diff --git a/src/main/java/noppes/npcs/util/CustomNPCsThreader.java b/src/main/java/noppes/npcs/util/CustomNPCsThreader.java index 3019fb5b1..6ed04819d 100644 --- a/src/main/java/noppes/npcs/util/CustomNPCsThreader.java +++ b/src/main/java/noppes/npcs/util/CustomNPCsThreader.java @@ -4,5 +4,10 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class CustomNPCsThreader { + /** + * Executor used for all asynchronous profile and player data saves. + * It is single-threaded so submitted tasks run sequentially and the + * save order for a given player is preserved. + */ public static final Executor customNPCThread = Executors.newSingleThreadExecutor(); }