Skip to content

Commit

Permalink
Add more defensive code and backport
Browse files Browse the repository at this point in the history
  • Loading branch information
Jikoo committed Nov 12, 2023
1 parent 59238c8 commit 5adc8e3
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,21 @@

package com.lishid.openinv.internal.v1_19_R3;

import java.io.File;
import net.minecraft.Util;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtUtils;
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.apache.logging.log4j.LogManager;
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;

public class OpenPlayer extends CraftPlayer {

Expand Down Expand Up @@ -52,13 +58,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());
Expand All @@ -71,4 +73,71 @@ 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)
try {
Tag attach = oldData.get("Attach");
if (attach != null) {
newData.putUUID("Attach", NbtUtils.loadUUID(attach));
}
} catch (IllegalArgumentException ignored) {
// Likely will not re-mount successfully, but at least the mount will not be deleted.
}
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 <T extends Tag> void copyValue(
@NotNull CompoundTag source,
@NotNull CompoundTag target,
@NotNull String container,
@NotNull String key,
@NotNull Class<T> 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 <T extends Tag> @Nullable T getTag(
@NotNull CompoundTag container,
@NotNull String key,
@NotNull Class<T> dataType) {
Tag value = container.get(key);
if (value == null || !dataType.isAssignableFrom(value.getClass())) {
return null;
}
return dataType.cast(value);
}

private <T extends Tag> void setTag(
@NotNull CompoundTag container,
@NotNull String key,
@Nullable T data) {
if (data == null) {
container.remove(key);
} else {
container.put(key, data);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,20 @@
package com.lishid.openinv.internal.v1_20_R1;

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.NbtUtils;
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_R1.CraftServer;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;

public class OpenPlayer extends CraftPlayer {

Expand Down Expand Up @@ -52,13 +58,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());
Expand All @@ -71,4 +73,71 @@ 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)
try {
Tag attach = oldData.get("Attach");
if (attach != null) {
newData.putUUID("Attach", NbtUtils.loadUUID(attach));
}
} catch (IllegalArgumentException ignored) {
// Likely will not re-mount successfully, but at least the mount will not be deleted.
}
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 <T extends Tag> void copyValue(
@NotNull CompoundTag source,
@NotNull CompoundTag target,
@NotNull String container,
@NotNull String key,
@NotNull Class<T> 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 <T extends Tag> @Nullable T getTag(
@NotNull CompoundTag container,
@NotNull String key,
@NotNull Class<T> dataType) {
Tag value = container.get(key);
if (value == null || !dataType.isAssignableFrom(value.getClass())) {
return null;
}
return dataType.cast(value);
}

private <T extends Tag> void setTag(
@NotNull CompoundTag container,
@NotNull String key,
@Nullable T data) {
if (data == null) {
container.remove(key);
} else {
container.put(key, data);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.minecraft.Util;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.NumericTag;
import net.minecraft.nbt.Tag;
import net.minecraft.server.level.ServerPlayer;
Expand Down Expand Up @@ -81,7 +82,14 @@ private void revertSpecialValues(@NotNull CompoundTag newData, @Nullable Compoun
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"));
try {
Tag attach = oldData.get("Attach");
if (attach != null) {
newData.putUUID("Attach", NbtUtils.loadUUID(attach));
}
} catch (IllegalArgumentException ignored) {
// Likely will not re-mount successfully, but at least the mount will not be deleted.
}
newData.put("Entity", oldData.getCompound("Entity"));
newData.put("RootVehicle", oldData.getCompound("RootVehicle"));
}
Expand Down

0 comments on commit 5adc8e3

Please sign in to comment.