From cef4af80f05cf35b10acd6fed2c1ef3e10de4610 Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Sat, 15 Jun 2024 13:15:50 +0200 Subject: [PATCH] Update reflection in NMS/OBC --- .../lib/paper/players/PaperOffPlayer.java | 37 ++++----------- .../paper/reflect/PandalibPaperReflect.java | 4 ++ .../wrapper/craftbukkit/CraftItemStack.java | 6 --- .../minecraft/core/HolderLookupProvider.java | 18 +++++++ .../minecraft/core/RegistryAccess.java | 18 +++++++ .../wrapper/minecraft/nbt/CompoundTag.java | 6 +-- .../minecraft/server/MinecraftServer.java | 6 +++ .../wrapper/minecraft/world/ItemStack.java | 47 ++++++++++++++++--- .../minecraft/world/PlayerDataStorage.java | 11 +++-- .../lib/paper/util/PlayerDataWrapper.java | 10 ++-- 10 files changed, 110 insertions(+), 53 deletions(-) create mode 100644 pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/core/HolderLookupProvider.java create mode 100644 pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/core/RegistryAccess.java diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/players/PaperOffPlayer.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/players/PaperOffPlayer.java index 6cf7684..0b67b9c 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/players/PaperOffPlayer.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/players/PaperOffPlayer.java @@ -2,12 +2,8 @@ package fr.pandacube.lib.paper.players; import fr.pandacube.lib.paper.reflect.util.PrimaryWorlds; import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftServer; -import fr.pandacube.lib.paper.reflect.wrapper.dataconverter.MCDataConverter; -import fr.pandacube.lib.paper.reflect.wrapper.dataconverter.MCTypeRegistry; -import fr.pandacube.lib.paper.reflect.wrapper.minecraft.SharedConstants; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.NbtIo; -import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.Tag; import fr.pandacube.lib.paper.util.PlayerDataWrapper; import fr.pandacube.lib.paper.world.WorldUtil; import fr.pandacube.lib.players.standalone.AbstractOffPlayer; @@ -154,29 +150,17 @@ public interface PaperOffPlayer extends AbstractOffPlayer { /** * Gets the NBT data from the player-data file. * It will not work if the player is online, because the data on the file are not synchronized with real-time values. - * @param convertTag true to convert the data to the current MC version, false to keep the saved version - * @return the NBT data from the player-data file, or null if the file does not exists. + * @return the NBT data from the player-data file, or null if the file does not exist. * @throws IllegalStateException if the player is online. - * @throws IOException if an error occurs reading the data. */ - default CompoundTag getPlayerData(boolean convertTag) throws IOException { + default CompoundTag getPlayerData() { if (isOnline()) throw new IllegalStateException("Cannot access data file of " + getName() + " because they’re online."); - CompoundTag data = ReflectWrapper.wrapTyped(Bukkit.getServer(), CraftServer.class) + return ReflectWrapper.wrapTyped(Bukkit.getServer(), CraftServer.class) .getServer() .getPlayerList() .playerIo() - .getPlayerData(getUniqueId().toString()); - if (data != null && convertTag) { - int srcVersion = data.contains("DataVersion", Tag.TAG_ANY_NUMERIC()) ? data.getInt("DataVersion") : -1; - int destVersion = SharedConstants.getCurrentVersion().getDataVersion().getVersion(); - try { - data = MCDataConverter.convertTag(MCTypeRegistry.PLAYER(), data, srcVersion, destVersion); - } catch (Exception e) { - throw new IOException("Unable to upgrade data format of player " + getName() + " (" + getUniqueId() + ") from version " + destVersion + " to " + destVersion); - } - } - return data; + .load(getName(), getUniqueId().toString()).orElse(null); } /** @@ -184,10 +168,9 @@ public interface PaperOffPlayer extends AbstractOffPlayer { * It will not work if the player is online, because the data on the file are not synchronized with real-time values. * @return the NBT data from the player-data file. * @throws IllegalStateException if the player is online. - * @throws IOException if an error occurs reading the data. */ - default PlayerDataWrapper getPlayerDataWrapper() throws IOException { - return new PlayerDataWrapper(getPlayerData(true)); + default PlayerDataWrapper getPlayerDataWrapper() { + return new PlayerDataWrapper(getPlayerData()); } /** @@ -213,25 +196,23 @@ public interface PaperOffPlayer extends AbstractOffPlayer { * @return the file where the player-data is stored. */ default File getPlayerDataFile(boolean old) { - File playerDataDir = new File(WorldUtil.worldDir(PrimaryWorlds.PRIMARY_WORLDS.get(0)), "playerdata"); + File playerDataDir = new File(WorldUtil.worldDir(PrimaryWorlds.PRIMARY_WORLDS.getFirst()), "playerdata"); return new File(playerDataDir, getUniqueId() + (old ? ".dat_old" : ".dat")); } /** * Gets the player’s inventory. * @return the player’s inventory. - * @throws IOException if an error occurs reading the data. */ - default PlayerInventory getInventory() throws IOException { + default PlayerInventory getInventory() { return getPlayerDataWrapper().getInventory(); } /** * Gets the player’s enderchest. * @return the player’s enderchest. - * @throws IOException if an error occurs reading the data. */ - default Inventory getEnderChest() throws IOException { + default Inventory getEnderChest() { return getPlayerDataWrapper().getEnderChest(); } diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/PandalibPaperReflect.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/PandalibPaperReflect.java index 6a4a229..3a7f9ec 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/PandalibPaperReflect.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/PandalibPaperReflect.java @@ -24,6 +24,8 @@ import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.GameProfileArgu import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.ResourceLocationArgument; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.commands.Vec3Argument; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.BlockPos; +import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.HolderLookupProvider; +import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.RegistryAccess; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.Vec3i; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CollectionTag; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag; @@ -130,6 +132,8 @@ public class PandalibPaperReflect { thAcc.catchThrowable(() -> initWrapper(Vec3Argument.class, Vec3Argument.REFLECT.get())); // minecraft.core thAcc.catchThrowable(() -> initWrapper(BlockPos.class, BlockPos.REFLECT.get())); + thAcc.catchThrowable(() -> initWrapper(HolderLookupProvider.class, HolderLookupProvider.REFLECT.get())); + thAcc.catchThrowable(() -> initWrapper(RegistryAccess.class, RegistryAccess.REFLECT.get())); thAcc.catchThrowable(() -> initWrapper(Vec3i.class, Vec3i.REFLECT.get())); // minecraft.nbt thAcc.catchThrowable(() -> initWrapper(CollectionTag.class, CollectionTag.REFLECT.get())); diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/craftbukkit/CraftItemStack.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/craftbukkit/CraftItemStack.java index 9cc4243..b19335a 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/craftbukkit/CraftItemStack.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/craftbukkit/CraftItemStack.java @@ -1,7 +1,6 @@ package fr.pandacube.lib.paper.reflect.wrapper.craftbukkit; import fr.pandacube.lib.paper.reflect.OBCReflect; -import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag; import fr.pandacube.lib.reflect.ReflectClass; import fr.pandacube.lib.reflect.ReflectMethod; import fr.pandacube.lib.reflect.wrapper.ReflectWrapperTyped; @@ -20,11 +19,6 @@ public class CraftItemStack extends ReflectWrapperTyped { } - public static ItemStack asCraftMirror(CompoundTag nbt) { - return asCraftMirror(fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.ItemStack.of(nbt)); - } - - public static fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.ItemStack asNMSCopy(ItemStack original) { return wrap(wrapReflectEx(() -> asNMSCopy.invokeStatic(original)), fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.ItemStack.class); } diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/core/HolderLookupProvider.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/core/HolderLookupProvider.java new file mode 100644 index 0000000..52cbeb2 --- /dev/null +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/core/HolderLookupProvider.java @@ -0,0 +1,18 @@ +package fr.pandacube.lib.paper.reflect.wrapper.minecraft.core; + +import fr.pandacube.lib.reflect.Reflect; +import fr.pandacube.lib.reflect.ReflectClass; +import fr.pandacube.lib.reflect.wrapper.ReflectWrapper; +import fr.pandacube.lib.reflect.wrapper.ReflectWrapperI; + +import static fr.pandacube.lib.util.ThrowableUtil.wrapEx; + +public interface HolderLookupProvider extends ReflectWrapperI { + ReflectClass REFLECT = wrapEx(() -> Reflect.ofClass("net.minecraft.core.HolderLookup.Provider")); + + class __concrete extends ReflectWrapper implements HolderLookupProvider { + protected __concrete(Object obj) { + super(obj); + } + } +} diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/core/RegistryAccess.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/core/RegistryAccess.java new file mode 100644 index 0000000..0295e62 --- /dev/null +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/core/RegistryAccess.java @@ -0,0 +1,18 @@ +package fr.pandacube.lib.paper.reflect.wrapper.minecraft.core; + +import fr.pandacube.lib.paper.reflect.wrapper.minecraft.network.protocol.custom.CustomPacketPayload; +import fr.pandacube.lib.reflect.Reflect; +import fr.pandacube.lib.reflect.ReflectClass; +import fr.pandacube.lib.reflect.wrapper.ReflectWrapper; + +import static fr.pandacube.lib.util.ThrowableUtil.wrapEx; + +public interface RegistryAccess extends HolderLookupProvider { + ReflectClass REFLECT = wrapEx(() -> Reflect.ofClass("net.minecraft.core.RegistryAccess")); + + class __concrete extends ReflectWrapper implements RegistryAccess { + protected __concrete(Object obj) { + super(obj); + } + } +} diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/nbt/CompoundTag.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/nbt/CompoundTag.java index 31899e6..95e29b3 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/nbt/CompoundTag.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/nbt/CompoundTag.java @@ -51,7 +51,7 @@ public class CompoundTag extends ReflectWrapper implements Tag { private static final ReflectMethod get = wrapEx(() -> REFLECT.method("get", String.class)); private static final ReflectMethod getAllKeys = wrapEx(() -> REFLECT.method("getAllKeys")); - private static final ReflectMethod entries = wrapEx(() -> REFLECT.method("entries")); + private static final ReflectMethod entrySet = wrapEx(() -> REFLECT.method("entrySet")); private static final ReflectMethod size = wrapEx(() -> REFLECT.method("size")); private static final ReflectMethod contains = wrapEx(() -> REFLECT.method("contains", String.class)); private static final ReflectMethod containsStringInt = wrapEx(() -> REFLECT.method("contains", String.class, int.class)); @@ -166,9 +166,9 @@ public class CompoundTag extends ReflectWrapper implements Tag { * The values in the returned Map are not wrapped. */ @SuppressWarnings("unchecked") - public Map entries() { + public Set> entrySet() { // we cannot easily wrap every value of the map without being able to synchronize the returned map with the wrapped map - return (Map) wrapReflectEx(() -> entries.invoke(__getRuntimeInstance())); + return (Set>) wrapReflectEx(() -> entrySet.invoke(__getRuntimeInstance())); } public int size() { return (int) wrapReflectEx(() -> size.invoke(__getRuntimeInstance())); diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/server/MinecraftServer.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/server/MinecraftServer.java index d8b9254..777b675 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/server/MinecraftServer.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/server/MinecraftServer.java @@ -1,5 +1,6 @@ package fr.pandacube.lib.paper.reflect.wrapper.minecraft.server; +import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.RegistryAccess; import fr.pandacube.lib.reflect.Reflect; import fr.pandacube.lib.reflect.ReflectClass; import fr.pandacube.lib.reflect.ReflectMethod; @@ -11,11 +12,16 @@ import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx; public class MinecraftServer extends ReflectWrapper { public static final ReflectClass REFLECT = wrapEx(() -> Reflect.ofClass("net.minecraft.server.MinecraftServer")); private static final ReflectMethod getPlayerList = wrapEx(() -> REFLECT.method("getPlayerList")); + public static final ReflectMethod registryAccess = wrapEx(() -> REFLECT.method("registryAccess")); public PlayerList getPlayerList() { return wrap(wrapReflectEx(() -> getPlayerList.invoke(__getRuntimeInstance())), PlayerList.class); } + public RegistryAccess registryAccess() { + return wrap(wrapReflectEx(() -> registryAccess.invoke(__getRuntimeInstance())), RegistryAccess.class); + } + protected MinecraftServer(Object obj) { super(obj); } diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/world/ItemStack.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/world/ItemStack.java index 7a87d1d..234ad44 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/world/ItemStack.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/world/ItemStack.java @@ -1,21 +1,35 @@ package fr.pandacube.lib.paper.reflect.wrapper.minecraft.world; -import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag; +import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftServer; +import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.HolderLookupProvider; +import fr.pandacube.lib.paper.reflect.wrapper.minecraft.core.RegistryAccess; +import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.Tag; import fr.pandacube.lib.reflect.Reflect; import fr.pandacube.lib.reflect.ReflectClass; import fr.pandacube.lib.reflect.ReflectMethod; import fr.pandacube.lib.reflect.wrapper.ReflectWrapper; +import org.bukkit.Bukkit; + +import java.util.Optional; import static fr.pandacube.lib.util.ThrowableUtil.wrapEx; import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx; public class ItemStack extends ReflectWrapper { public static final ReflectClass REFLECT = wrapEx(() -> Reflect.ofClass("net.minecraft.world.item.ItemStack")); - private static final ReflectMethod of = wrapEx(() -> REFLECT.method("of", CompoundTag.REFLECT.get())); - private static final ReflectMethod save = wrapEx(() -> REFLECT.method("save", CompoundTag.REFLECT.get())); + private static final ReflectMethod parse = wrapEx(() -> REFLECT.method("parse", HolderLookupProvider.REFLECT.get(), Tag.REFLECT.get())); + private static final ReflectMethod saveWithPrefix = wrapEx(() -> REFLECT.method("save", HolderLookupProvider.REFLECT.get(), Tag.REFLECT.get())); + private static final ReflectMethod save = wrapEx(() -> REFLECT.method("save", HolderLookupProvider.REFLECT.get())); - public static ItemStack of(CompoundTag nbt) { - return wrap(wrapReflectEx(() -> of.invokeStatic(unwrap(nbt))), ItemStack.class); + @SuppressWarnings("unchecked") + public static Optional parse(HolderLookupProvider registries, Tag nbt) { + return ((Optional) wrapReflectEx(() -> parse.invokeStatic(unwrap(registries), unwrap(nbt)))) + .map(o -> wrap(o, ItemStack.class)); + } + + + public static Optional parse(Tag nbt) { + return parse(getRegistries(), nbt); } @@ -24,7 +38,26 @@ public class ItemStack extends ReflectWrapper { } - public CompoundTag save(CompoundTag nbt) { - return wrap(wrapReflectEx(() -> save.invoke(__getRuntimeInstance(), unwrap(nbt))), CompoundTag.class); + public Tag save(HolderLookupProvider registries, Tag prefix) { + return wrap(wrapReflectEx(() -> saveWithPrefix.invoke(__getRuntimeInstance(), unwrap(registries), unwrap(prefix))), Tag.class); + } + + + public Tag save(HolderLookupProvider registries) { + return wrap(wrapReflectEx(() -> save.invoke(__getRuntimeInstance(), unwrap(registries))), Tag.class); + } + + + public Tag save(Tag prefix) { + return save(getRegistries(), prefix); + } + + + public Tag save() { + return save(getRegistries()); + } + + private static RegistryAccess getRegistries() { + return wrap(Bukkit.getServer(), CraftServer.class).getServer().registryAccess(); } } diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/world/PlayerDataStorage.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/world/PlayerDataStorage.java index d00a4bd..bbacb2d 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/world/PlayerDataStorage.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/reflect/wrapper/minecraft/world/PlayerDataStorage.java @@ -6,18 +6,23 @@ import fr.pandacube.lib.reflect.ReflectClass; import fr.pandacube.lib.reflect.ReflectMethod; import fr.pandacube.lib.reflect.wrapper.ReflectWrapper; +import java.util.Optional; + import static fr.pandacube.lib.util.ThrowableUtil.wrapEx; import static fr.pandacube.lib.util.ThrowableUtil.wrapReflectEx; public class PlayerDataStorage extends ReflectWrapper { public static final ReflectClass REFLECT = wrapEx(() -> Reflect.ofClass("net.minecraft.world.level.storage.PlayerDataStorage")); - public static final ReflectMethod getPlayerData = wrapEx(() -> REFLECT.method("getPlayerData", String.class)); // Craftbukkit method + public static final ReflectMethod load = wrapEx(() -> REFLECT.method("load", String.class, String.class)); /** + * @param playerName the name of the player: used for loading error message and of offline UUID generation. * @param playerId UUID of a player as it is used to name the player data file (UUID.toString()) */ - public CompoundTag getPlayerData(String playerId) { - return wrap(wrapReflectEx(() -> getPlayerData.invoke(__getRuntimeInstance(), playerId)), CompoundTag.class); + @SuppressWarnings("unchecked") + public Optional load(String playerName, String playerId) { + return ((Optional) wrapReflectEx(() -> load.invoke(__getRuntimeInstance(), playerId))) + .map(o -> wrap(o, CompoundTag.class)); } diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/util/PlayerDataWrapper.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/util/PlayerDataWrapper.java index 54596e2..fd7c06c 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/util/PlayerDataWrapper.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/util/PlayerDataWrapper.java @@ -116,10 +116,9 @@ public record PlayerDataWrapper(CompoundTag data) { for (int i = 0; i < list.size(); i++) { CompoundTag itemTag = list.getCompound(i); int nbtSlot = itemTag.getByte("Slot") & 255; - ItemStack is = filterStack(CraftItemStack.asCraftMirror(itemTag)); - if (is != null) { - stacks.put(nbtSlot, CraftItemStack.asCraftMirror(itemTag)); - } + fr.pandacube.lib.paper.reflect.wrapper.minecraft.world.ItemStack.parse(itemTag) + .map(nms -> filterStack(CraftItemStack.asCraftMirror(nms))) + .ifPresent(is -> stacks.put(nbtSlot, is)); } return stacks; } @@ -148,9 +147,8 @@ public record PlayerDataWrapper(CompoundTag data) { if (stack == null) continue; CompoundTag itemTag = new CompoundTag(); - CraftItemStack.asNMSCopy(is.getValue()).save(itemTag); itemTag.putByte("Slot", is.getKey().byteValue()); - list.add(list.size(), itemTag); + list.add(list.size(), CraftItemStack.asNMSCopy(is.getValue()).save(itemTag)); } data.put(key, list); }