curios snbt clean

This commit is contained in:
mlus 2026-02-23 22:33:13 +08:00
parent bc71c59a45
commit b6da709393
8 changed files with 22 additions and 24 deletions

View File

@ -1,10 +1,11 @@
package vip.fubuki.playersync.config; package vip.fubuki.playersync.config;
import net.neoforged.neoforge.common.ModConfigSpec;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import net.neoforged.neoforge.common.ModConfigSpec;
public class JdbcConfig { public class JdbcConfig {

View File

@ -1,6 +1,5 @@
package vip.fubuki.playersync.mixin.cobblemon; package vip.fubuki.playersync.mixin.cobblemon;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.api.pokedex.PokedexManager; import com.cobblemon.mod.common.api.pokedex.PokedexManager;
import com.cobblemon.mod.common.api.storage.player.InstancedPlayerData; import com.cobblemon.mod.common.api.storage.player.InstancedPlayerData;
import com.cobblemon.mod.common.api.storage.player.adapter.NbtBackedPlayerData; import com.cobblemon.mod.common.api.storage.player.adapter.NbtBackedPlayerData;

View File

@ -4,7 +4,6 @@ import com.cobblemon.mod.common.api.storage.pc.PCStore;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.core.RegistryAccess; import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.TagParser; import net.minecraft.nbt.TagParser;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -4,7 +4,6 @@ import com.cobblemon.mod.common.api.storage.party.PartyStore;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.core.RegistryAccess; import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.TagParser; import net.minecraft.nbt.TagParser;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;

View File

@ -36,7 +36,6 @@ import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.event.OnDatapackSyncEvent; import net.neoforged.neoforge.event.OnDatapackSyncEvent;
import net.neoforged.neoforge.event.entity.living.LivingDeathEvent; import net.neoforged.neoforge.event.entity.living.LivingDeathEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent;
import net.neoforged.neoforge.event.entity.player.PlayerNegotiationEvent; import net.neoforged.neoforge.event.entity.player.PlayerNegotiationEvent;
import net.neoforged.neoforge.event.server.ServerStoppedEvent; import net.neoforged.neoforge.event.server.ServerStoppedEvent;
import net.neoforged.neoforge.event.tick.LevelTickEvent; import net.neoforged.neoforge.event.tick.LevelTickEvent;
@ -372,7 +371,7 @@ public class VanillaSync {
} }
// deserialize item and potentially create placeholders // deserialize item and potentially create placeholders
private static ItemStack deserializeAndCreatePlaceholderIfNeeded(String serializedNbt) public static ItemStack deserializeAndCreatePlaceholderIfNeeded(String serializedNbt)
throws CommandSyntaxException { throws CommandSyntaxException {
if (serializedNbt == null || serializedNbt.isEmpty() || serializedNbt.equals("B64:e30=")) { if (serializedNbt == null || serializedNbt.isEmpty() || serializedNbt.equals("B64:e30=")) {
// Check for empty NBT (Base64 encoded '{}') // Check for empty NBT (Base64 encoded '{}')
@ -380,7 +379,7 @@ public class VanillaSync {
} }
String nbtString = deserializeString(serializedNbt); String nbtString = deserializeString(serializedNbt);
CompoundTag compoundTag = TagParser.parseTag(LocalJsonUtil.cleanSnbt(nbtString)); CompoundTag compoundTag = TagParser.parseTag(nbtString);
if (compoundTag.isEmpty() || !compoundTag.contains("id", Tag.TAG_STRING)) { if (compoundTag.isEmpty() || !compoundTag.contains("id", Tag.TAG_STRING)) {
return ItemStack.EMPTY; // Invalid or empty tag return ItemStack.EMPTY; // Invalid or empty tag
@ -489,11 +488,13 @@ public class VanillaSync {
} }
} }
// Legacy fallback using custom replacement // Legacy fallback using custom replacement
return encoded.replace("|", ",") // cleanSnbt is applied here because legacy serialization could produce stray {"":""} type markers
// B64-decoded data must NOT be cleaned as it contains verbatim NBT from modern mods
return LocalJsonUtil.cleanSnbt(encoded.replace("|", ",")
.replace("^", "\"") .replace("^", "\"")
.replace("<", "{") .replace("<", "{")
.replace(">", "}") .replace(">", "}")
.replace("~", "'"); .replace("~", "'"));
} }
/** /**
@ -574,7 +575,7 @@ public class VanillaSync {
// Helper function to get the NBT string to be saved // Helper function to get the NBT string to be saved
// If item is a placeholder, get original NBT; otherwise, get current NBT // If item is a placeholder, get original NBT; otherwise, get current NBT
private static String getNbtForStorage(ItemStack itemStack) { public static String getNbtForStorage(ItemStack itemStack) {
if (itemStack.is(Items.PAPER) && itemStack.getComponents().has(DataComponents.CUSTOM_DATA) if (itemStack.is(Items.PAPER) && itemStack.getComponents().has(DataComponents.CUSTOM_DATA)
&& itemStack.getComponents().get(DataComponents.CUSTOM_DATA).contains("playersync:original_item_nbt")) { && itemStack.getComponents().get(DataComponents.CUSTOM_DATA).contains("playersync:original_item_nbt")) {
// It's our placeholder, retrieve the original NBT string // It's our placeholder, retrieve the original NBT string

View File

@ -4,7 +4,6 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameRules;
import net.neoforged.fml.ModList; import net.neoforged.fml.ModList;
import top.theillusivec4.curios.api.CuriosApi; import top.theillusivec4.curios.api.CuriosApi;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler; import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
@ -72,7 +71,7 @@ public class CuriosCache {
for (int i = 0; i < dynStacks.getSlots(); i++) { for (int i = 0; i < dynStacks.getSlots(); i++) {
ItemStack stack = dynStacks.getStackInSlot(i); ItemStack stack = dynStacks.getStackInSlot(i);
if (!stack.isEmpty()) { if (!stack.isEmpty()) {
String serialized = VanillaSync.serialize(VanillaSync.serializeNBT(stack).toString()); String serialized = VanillaSync.getNbtForStorage(stack);
flatMap.put(slotType + ":" + i, serialized); flatMap.put(slotType + ":" + i, serialized);
} }
} }

View File

@ -2,12 +2,10 @@ package vip.fubuki.playersync.sync.addons;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.TagParser; import net.minecraft.nbt.TagParser;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.neoforged.fml.ModList; import net.neoforged.fml.ModList;
import net.neoforged.neoforge.server.ServerLifecycleHooks;
import top.theillusivec4.curios.api.CuriosApi; import top.theillusivec4.curios.api.CuriosApi;
import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler; import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler;
import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler; import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler;
@ -44,7 +42,7 @@ public class ModsSupport {
if (rsBackpack.next()) { if (rsBackpack.next()) {
String serialized = rsBackpack.getString("backpack_nbt"); String serialized = rsBackpack.getString("backpack_nbt");
String nbtString = VanillaSync.deserializeString(serialized); String nbtString = VanillaSync.deserializeString(serialized);
CompoundTag backpackNbt = TagParser.parseTag(LocalJsonUtil.cleanSnbt(nbtString)); CompoundTag backpackNbt = TagParser.parseTag(nbtString);
// Update BackpackStorage with the retrieved NBT // Update BackpackStorage with the retrieved NBT
net.p3pp3rf1y.sophisticatedbackpacks.backpack.BackpackStorage.get().setBackpackContents(contentsUuid, backpackNbt); net.p3pp3rf1y.sophisticatedbackpacks.backpack.BackpackStorage.get().setBackpackContents(contentsUuid, backpackNbt);
PlayerSync.LOGGER.info("Restored backpack data for UUID " + contentsUuid); PlayerSync.LOGGER.info("Restored backpack data for UUID " + contentsUuid);
@ -97,22 +95,21 @@ public class ModsSupport {
handlerOpt.ifPresent(handler -> { handlerOpt.ifPresent(handler -> {
for (Map.Entry<String, String> entry : storedMap.entrySet()) { for (Map.Entry<String, String> entry : storedMap.entrySet()) {
String compositeKey = entry.getKey(); // Expected format: "slotType:index" String compositeKey = entry.getKey(); // Expected format: "slotType:index"
String[] parts = compositeKey.split(":"); // Use lastIndexOf to correctly handle slot type names that may contain ':'
if (parts.length != 2) { int lastColon = compositeKey.lastIndexOf(':');
if (lastColon < 0) {
continue; continue;
} }
String slotType = parts[0]; String slotType = compositeKey.substring(0, lastColon);
int slotIndex; int slotIndex;
try { try {
slotIndex = Integer.parseInt(parts[1]); slotIndex = Integer.parseInt(compositeKey.substring(lastColon + 1));
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
continue; continue;
} }
String serialized = entry.getValue(); String serialized = entry.getValue();
try { try {
String nbtString = VanillaSync.deserializeString(serialized); ItemStack stack = VanillaSync.deserializeAndCreatePlaceholderIfNeeded(serialized);
CompoundTag tag = TagParser.parseTag(LocalJsonUtil.cleanSnbt(nbtString));
ItemStack stack = ItemStack.parse(ServerLifecycleHooks.getCurrentServer().registryAccess(),tag).get();
if (handler.getCurios().containsKey(slotType)) { if (handler.getCurios().containsKey(slotType)) {
ICurioStacksHandler stacksHandler = handler.getCurios().get(slotType); ICurioStacksHandler stacksHandler = handler.getCurios().get(slotType);
IDynamicStackHandler dynStacks = stacksHandler.getStacks(); IDynamicStackHandler dynStacks = stacksHandler.getStacks();
@ -155,7 +152,7 @@ public class ModsSupport {
for (int i = 0; i < dynStacks.getSlots(); i++) { for (int i = 0; i < dynStacks.getSlots(); i++) {
ItemStack stack = dynStacks.getStackInSlot(i); ItemStack stack = dynStacks.getStackInSlot(i);
if (!stack.isEmpty()) { if (!stack.isEmpty()) {
String serialized = VanillaSync.serialize(VanillaSync.serializeNBT(stack).toString()); String serialized = VanillaSync.getNbtForStorage(stack);
flatMap.put(slotType + ":" + i, serialized); flatMap.put(slotType + ":" + i, serialized);
} }
} }

View File

@ -3,7 +3,10 @@ package vip.fubuki.playersync.sync.chat;
import vip.fubuki.playersync.PlayerSync; import vip.fubuki.playersync.PlayerSync;
import vip.fubuki.playersync.config.JdbcConfig; import vip.fubuki.playersync.config.JdbcConfig;
import java.io.*; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;