From 79e884234fdde877aa211123a11330a4e9e9a5d5 Mon Sep 17 00:00:00 2001 From: Jikoo Date: Sun, 12 Nov 2023 01:59:24 -0500 Subject: [PATCH] Expand preserved old data - Fix play timestamps being erroneously updated - Fix vehicle possibly not being re-mounted --- .../openinv/internal/v1_20_R2/OpenPlayer.java | 75 +++++++++++++++++-- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/internal/v1_20_R2/src/main/java/com/lishid/openinv/internal/v1_20_R2/OpenPlayer.java b/internal/v1_20_R2/src/main/java/com/lishid/openinv/internal/v1_20_R2/OpenPlayer.java index 42398ea4..fdaa0d49 100644 --- a/internal/v1_20_R2/src/main/java/com/lishid/openinv/internal/v1_20_R2/OpenPlayer.java +++ b/internal/v1_20_R2/src/main/java/com/lishid/openinv/internal/v1_20_R2/OpenPlayer.java @@ -17,14 +17,19 @@ package com.lishid.openinv.internal.v1_20_R2; import com.mojang.logging.LogUtils; -import java.io.File; import net.minecraft.Util; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.NumericTag; +import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.storage.PlayerDataStorage; import org.bukkit.craftbukkit.v1_20_R2.CraftServer; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; public class OpenPlayer extends CraftPlayer { @@ -48,13 +53,9 @@ public void saveData() { setExtraData(playerData); if (!isOnline()) { - // Special case: save old vehicle data + // Preserve certain data when offline. CompoundTag oldData = worldNBTStorage.load(player); - - if (oldData != null && oldData.contains("RootVehicle", 10)) { - // See net.minecraft.server.PlayerList#a(NetworkManager, EntityPlayer) and net.minecraft.server.EntityPlayer#b(NBTTagCompound) - playerData.put("RootVehicle", oldData.getCompound("RootVehicle")); - } + revertSpecialValues(playerData, oldData); } File file = File.createTempFile(player.getStringUUID() + "-", ".dat", worldNBTStorage.getPlayerDir()); @@ -67,4 +68,64 @@ public void saveData() { } } + private void revertSpecialValues(@NotNull CompoundTag newData, @Nullable CompoundTag oldData) { + if (oldData == null) { + return; + } + + // Prevent vehicle deletion. + if (oldData.contains("RootVehicle", Tag.TAG_COMPOUND)) { + // See net.minecraft.server.players.PlayerList#save(ServerPlayer) + // See net.minecraft.server.level.ServerPlayer#addAdditionalSaveData(CompoundTag) + newData.putUUID("Attach", oldData.getUUID("Attach")); + newData.put("Entity", oldData.getCompound("Entity")); + newData.put("RootVehicle", oldData.getCompound("RootVehicle")); + } + + // Revert automatic updates to play timestamps. + copyValue(newData, oldData, "bukkit", "lastPlayed", NumericTag.class); + copyValue(newData, oldData, "Paper", "LastSeen", NumericTag.class); + copyValue(newData, oldData, "Paper", "LastLogin", NumericTag.class); + } + + private void copyValue( + @NotNull CompoundTag source, + @NotNull CompoundTag target, + @NotNull String container, + @NotNull String key, + @NotNull Class tagType) { + CompoundTag oldContainer = getTag(source, container, CompoundTag.class); + CompoundTag newContainer = getTag(target, container, CompoundTag.class); + + // Container being null means the server implementation doesn't store this data. + if (oldContainer == null || newContainer == null) { + return; + } + + // If old tag exists, copy it to new location, removing otherwise. + setTag(newContainer, key, getTag(oldContainer, key, tagType)); + } + + private @Nullable T getTag( + @NotNull CompoundTag container, + @NotNull String key, + @NotNull Class dataType) { + Tag value = container.get(key); + if (value == null || !dataType.isAssignableFrom(value.getClass())) { + return null; + } + return dataType.cast(value); + } + + private void setTag( + @NotNull CompoundTag container, + @NotNull String key, + @Nullable T data) { + if (data == null) { + container.remove(key); + } else { + container.put(key, data); + } + } + }