Fix anti-duplication: clear slots before restoring data

This commit is contained in:
laforetbrut 2026-04-04 07:16:50 +02:00
parent a8c0cb50af
commit eec949f405
2 changed files with 36 additions and 26 deletions

View File

@ -155,17 +155,15 @@ public class ModCompatSync {
*/
public static void applyAccessoriesFromData(Player player, String accessoriesData) {
if (!ModList.get().isLoaded("accessories")) return;
if (accessoriesData == null || accessoriesData.length() <= 2) return;
try {
io.wispforest.accessories.api.AccessoriesCapability cap =
io.wispforest.accessories.api.AccessoriesCapability.get(player);
if (cap == null) return;
Map<String, String> storedMap = LocalJsonUtil.StringToMap(accessoriesData);
if (storedMap.isEmpty()) return;
Map<String, io.wispforest.accessories.api.AccessoriesContainer> containers = cap.getContainers();
// FIX ANTI-DUPLICATION: ALWAYS clear accessories slots first to wipe stale
// data from Minecraft's .dat file, then only restore if DB has valid data.
for (io.wispforest.accessories.api.AccessoriesContainer container : containers.values()) {
var accessories = container.getAccessories();
for (int i = 0; i < accessories.getContainerSize(); i++) {
@ -173,6 +171,11 @@ public class ModCompatSync {
}
}
if (accessoriesData == null || accessoriesData.length() <= 2) return;
Map<String, String> storedMap = LocalJsonUtil.StringToMap(accessoriesData);
if (storedMap.isEmpty()) return;
for (Map.Entry<String, String> entry : storedMap.entrySet()) {
String compositeKey = entry.getKey();
int lastColon = compositeKey.lastIndexOf(':');
@ -308,19 +311,22 @@ public class ModCompatSync {
*/
public static void applyCosmeticArmorFromData(Player player, String cosmeticArmorData) {
if (!ModList.get().isLoaded("cosmeticarmorreworked")) return;
if (cosmeticArmorData == null || cosmeticArmorData.length() <= 2) return;
try {
lain.mods.cos.impl.inventory.InventoryCosArmor cosInv =
lain.mods.cos.impl.ModObjects.invMan.getCosArmorInventory(player.getUUID());
if (cosInv == null) return;
Map<Integer, String> storedMap = LocalJsonUtil.StringToEntryMap(cosmeticArmorData);
if (storedMap.isEmpty()) return;
// FIX ANTI-DUPLICATION: ALWAYS clear cosmetic armor slots first to wipe stale
// data from Minecraft's .dat file, then only restore if DB has valid data.
for (int i = 0; i < cosInv.getContainerSize(); i++) {
cosInv.setItem(i, ItemStack.EMPTY);
}
if (cosmeticArmorData == null || cosmeticArmorData.length() <= 2) return;
Map<Integer, String> storedMap = LocalJsonUtil.StringToEntryMap(cosmeticArmorData);
if (storedMap.isEmpty()) return;
for (Map.Entry<Integer, String> entry : storedMap.entrySet()) {
int slot = entry.getKey();
try {

View File

@ -152,21 +152,10 @@ public class ModsSupport {
curiosData = rs.getString("curios_item");
}
// FIX: Check if data is valid BEFORE clearing slots
if (curiosData == null || curiosData.length() <= 2) {
PlayerSync.LOGGER.debug("Empty curios data for player {}, skipping restore", player.getUUID());
return;
}
Map<String, String> storedMap = LocalJsonUtil.StringToMap(curiosData);
if (storedMap.isEmpty()) {
PlayerSync.LOGGER.debug("No curios entries for player {}, skipping restore", player.getUUID());
return;
}
ICuriosItemHandler handler = handlerOpt.get();
// Clear current Curios slots ONLY after confirming valid data exists
// FIX ANTI-DUPLICATION: ALWAYS clear curios slots first to wipe stale data
// loaded from Minecraft's .dat file, then only restore if DB has valid data.
handler.getCurios().forEach((slotType, stacksHandler) -> {
IDynamicStackHandler dynStacks = stacksHandler.getStacks();
for (int i = 0; i < dynStacks.getSlots(); i++) {
@ -174,6 +163,17 @@ public class ModsSupport {
}
});
if (curiosData == null || curiosData.length() <= 2) {
PlayerSync.LOGGER.debug("Empty curios data for player {}, slots cleared", player.getUUID());
return;
}
Map<String, String> storedMap = LocalJsonUtil.StringToMap(curiosData);
if (storedMap.isEmpty()) {
PlayerSync.LOGGER.debug("No curios entries for player {}, slots cleared", player.getUUID());
return;
}
// Restore each saved item
for (Map.Entry<String, String> entry : storedMap.entrySet()) {
String compositeKey = entry.getKey();
@ -267,7 +267,6 @@ public class ModsSupport {
*/
public static void applyCuriosFromData(Player player, String curiosData) {
if (!ModList.get().isLoaded("curios")) return;
if (curiosData == null || curiosData.length() <= 2) return;
Optional<ICuriosItemHandler> handlerOpt = CuriosApi.getCuriosInventory(player);
if (handlerOpt.isEmpty()) {
@ -275,12 +274,11 @@ public class ModsSupport {
return;
}
Map<String, String> storedMap = LocalJsonUtil.StringToMap(curiosData);
if (storedMap.isEmpty()) return;
ICuriosItemHandler handler = handlerOpt.get();
// Clear all curios slots BEFORE restoring
// FIX ANTI-DUPLICATION: ALWAYS clear curios slots first, even when DB data is
// empty. Without this, stale curios loaded from Minecraft's .dat file (world save)
// persist when the DB has no curios data causing item duplication across servers.
for (Map.Entry<String, ICurioStacksHandler> entry : handler.getCurios().entrySet()) {
IDynamicStackHandler stacks = entry.getValue().getStacks();
for (int i = 0; i < stacks.getSlots(); i++) {
@ -288,6 +286,12 @@ public class ModsSupport {
}
}
// If no data to restore, we're done (slots already cleared above)
if (curiosData == null || curiosData.length() <= 2) return;
Map<String, String> storedMap = LocalJsonUtil.StringToMap(curiosData);
if (storedMap.isEmpty()) return;
// Restore items from pre-read data
for (Map.Entry<String, String> entry : storedMap.entrySet()) {
String compositeKey = entry.getKey();