Fix backpack/shulker contents lost on transfer: never overwrite DB with empty data

ROOT CAUSE: Sophisticated Backpacks/Storage wrappers cache inventory
in memory. When store() reads from BackpackStorage/ItemContentsStorage,
the SavedData may not have the latest wrapper state (unflushed changes).
This returns empty/default NBT which overwrites the real data in our DB.

Going back to the original server showed data because that server's
local SavedData still had the correct data (never overwritten).

FIX: saveStorageContents() now checks if the NBT is empty/minimal
before writing. If the DB already has substantial data (>50 bytes)
and the new NBT is empty, the save is SKIPPED to preserve the real
data. This prevents the empty-overwrite scenario while still allowing
legitimate saves of actual content.

Vyrriox
This commit is contained in:
laforetbrut 2026-03-26 22:09:51 +01:00
parent e511414463
commit 7613f4ecfb

View File

@ -89,7 +89,28 @@ public class ModsSupport {
* Generic method to save storage contents to DB for a given UUID.
* Used for both Sophisticated Backpacks and Sophisticated Storage items.
*/
/**
* Saves storage contents to DB, but ONLY if the NBT contains real data.
* If the NBT is empty/default (wrapper didn't flush to SavedData yet),
* we skip the save to avoid overwriting real data in the DB with empty content.
* This prevents data loss when the in-memory SavedData doesn't have the latest
* wrapper state (common with Sophisticated Backpacks/Storage).
*/
private static void saveStorageContents(UUID contentsUuid, CompoundTag nbt) {
// Skip empty/minimal NBT to avoid overwriting real data in DB
if (nbt == null || nbt.isEmpty() || nbt.size() <= 1) {
// Check if DB already has data for this UUID - if so, don't overwrite with empty
try (JDBCsetUp.QueryResult qr = JDBCsetUp.executePreparedQuery(
"SELECT LENGTH(backpack_nbt) AS len FROM backpack_data WHERE uuid=?", contentsUuid.toString())) {
java.sql.ResultSet rs = qr.resultSet();
if (rs.next() && rs.getInt("len") > 50) {
PlayerSync.LOGGER.debug("Skipping save of empty/minimal NBT for UUID {} - DB has {} bytes of real data",
contentsUuid, rs.getInt("len"));
return;
}
} catch (Exception ignored) {}
}
String serialized = VanillaSync.serializeTagToBinaryBase64(nbt);
try {
JDBCsetUp.executePreparedUpdate(