Refactor pandalib-paper ReflectRegistry + fix some issues in Reflect util class

This commit is contained in:
2022-02-17 22:59:50 +01:00
parent 06b89bd271
commit ad74ed2854
5 changed files with 264 additions and 151 deletions

View File

@@ -2,12 +2,18 @@ package fr.pandacube.lib.paper;
import org.bukkit.plugin.Plugin;
import fr.pandacube.lib.paper.reflect.ReflectRegistry;
public class PandaLibPaper {
private static Plugin plugin;
public static void init(Plugin plugin) {
PandaLibPaper.plugin = plugin;
ReflectRegistry.init();
}
public static Plugin getPlugin() {

View File

@@ -46,6 +46,11 @@ public class NMSReflect {
OBF_NAMESPACE = (String) PAPER_OBFHELPER_CLASS.field("SPIGOT_NAMESPACE").getStaticValue();
MOJ_NAMESPACE = (String) PAPER_OBFHELPER_CLASS.field("MOJANG_PLUS_YARN_NAMESPACE").getStaticValue();
} catch (ReflectiveOperationException e) {
throw new RuntimeException("Unable to find the Paper ofbuscation mapping class or class members.", e);
}
try {
List<ClassMapping> mappings = loadMappings();
for (ClassMapping clazz : mappings) {
@@ -119,8 +124,7 @@ public class NMSReflect {
private static List<ClassMapping> loadMappings() {
try (final InputStream mappingsInputStream = PAPER_OBFHELPER_CLASS.get().getClassLoader().getResourceAsStream("META-INF/mappings/reobf.tiny")) {
if (mappingsInputStream == null) {
Log.severe("Unable to find the ofbuscation mapping file in the Paper jar.");
return Collections.emptyList();
throw new RuntimeException("Unable to find the ofbuscation mapping file in the Paper jar.");
}
MemoryMappingTree tree = new MemoryMappingTree();

View File

@@ -1,11 +1,14 @@
package fr.pandacube.lib.paper.reflect;
import static fr.pandacube.lib.core.util.ThrowableUtil.wrapEx;
import org.bukkit.NamespacedKey;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import com.mojang.brigadier.tree.CommandNode;
import fr.pandacube.lib.core.util.Log;
import fr.pandacube.lib.core.util.Reflect;
import fr.pandacube.lib.core.util.Reflect.ReflectClass;
import fr.pandacube.lib.core.util.Reflect.ReflectConstructor;
@@ -13,131 +16,189 @@ import fr.pandacube.lib.core.util.Reflect.ReflectField;
import fr.pandacube.lib.core.util.Reflect.ReflectMethod;
import fr.pandacube.lib.paper.reflect.NMSReflect.ClassMapping;
/**
* Collection of static properties to ease access to commonly used server internals and private class members.
*/
public class ReflectRegistry {
public static final class NMS {
public static final class SharedConstants {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.SharedConstants"));
public static final ReflectMethod<?> getCurrentVersion = wrapEx(() -> MAPPING.mojMethod("getCurrentVersion"));
}
public static final class WorldVersion {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.WorldVersion"));
public static final ReflectMethod<?> getProtocolVersion = wrapEx(() -> MAPPING.runtimeReflect().method("getProtocolVersion"));
}
public static final class DedicatedServer {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.dedicated.DedicatedServer"));
public static final ReflectField<?> vanillaCommandDispatcher = wrapEx(() -> MAPPING.runtimeReflect().field("vanillaCommandDispatcher"));
}
public static final class Commands {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.Commands"));
public static final ReflectField<?> dispatcher = wrapEx(() -> DedicatedServer.MAPPING.mojField("dispatcher")); // TODO vérifier
}
public static final class Vec3 {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.phys.Vec3"));
}
public static final class Component {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.network.chat.Component"));
}
public static final class CommandSourceStack {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.CommandSourceStack"));
}
public static final class EntityArgument {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.EntityArgument"));
public static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor(boolean.class, boolean.class));
}
public static final ClassMapping NMS_SHAREDCONSTANTS = wrapEx(() -> NMSReflect.mojClass("net.minecraft.SharedConstants"));
public static final ReflectMethod<?> NMS_SHAREDCONSTANTS_GETCURRENTVERSION = wrapEx(() -> NMS_SHAREDCONSTANTS.mojMethod("getCurrentVersion"));
public static final ClassMapping NMS_WORLDVERSION = wrapEx(() -> NMSReflect.mojClass("net.minecraft.WorldVersion"));
public static final ReflectMethod<?> NMS_WORLDVERSION_GETPROTOCOLVERSION = wrapEx(() -> NMS_WORLDVERSION.runtimeReflect().method("getProtocolVersion"));
public static final ClassMapping NMS_DEDICATEDSERVER = wrapEx(() -> NMSReflect.mojClass("net.minecraft.server.dedicated.DedicatedServer"));
public static final ReflectField<?> NMS_DEDICATEDSERVER_VANILLACOMMANDDISPATCHER = wrapEx(() -> NMS_DEDICATEDSERVER.runtimeReflect().field("vanillaCommandDispatcher"));
public static final ClassMapping NMS_COMMANDS = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.Commands"));
public static final ReflectField<?> NMS_COMMANDS_DISPATCHER = wrapEx(() -> NMS_DEDICATEDSERVER.mojField("dispatcher"));
public static final class EntitySelector {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.selector.EntitySelector"));
public static final ReflectMethod<?> findEntities = wrapEx(() -> MAPPING.mojMethod("findEntities", CommandSourceStack.MAPPING));
public static final ReflectMethod<?> findPlayers = wrapEx(() -> MAPPING.mojMethod("findPlayers", CommandSourceStack.MAPPING));
public static final ReflectMethod<?> findSingleEntity = wrapEx(() -> MAPPING.mojMethod("findSingleEntity", CommandSourceStack.MAPPING));
public static final ReflectMethod<?> findSinglePlayer = wrapEx(() -> MAPPING.mojMethod("findSinglePlayer", CommandSourceStack.MAPPING));
}
public static final class Entity {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.entity.Entity"));
public static final ReflectMethod<?> getBukkitEntity = wrapEx(() -> MAPPING.runtimeReflect().method("getBukkitEntity"));
}
public static final ClassMapping NMS_VEC3 = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.phys.Vec3"));
public static final ClassMapping NMS_COMPONENT = wrapEx(() -> NMSReflect.mojClass("net.minecraft.network.chat.Component"));
public static final class ComponentArgument {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.ComponentArgument"));
public static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor());
}
public static final class BlockStateArgument {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.blocks.BlockStateArgument"));
public static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor());
}
public static final class Vec3Argument {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.coordinates.Vec3Argument"));
public static final ReflectMethod<?> vec3 = wrapEx(() -> MAPPING.mojMethod("vec3", boolean.class));
}
public static final ClassMapping NMS_COMMANDSOURCESTACK = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.CommandSourceStack"));
public static final ClassMapping NMS_ENTITYARGUMENT = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.EntityArgument"));
public static final ReflectConstructor<?> NMS_ENTITYARGUMENT_CONSTRUCTOR = wrapEx(() -> NMS_ENTITYARGUMENT.runtimeReflect().constructor(boolean.class, boolean.class));
public static final ClassMapping NMS_ENTITYSELECTOR = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.selector.EntitySelector"));
public static final ReflectMethod<?> NMS_ENTITYSELECTOR_FINDENTITIES = wrapEx(() -> NMS_ENTITYSELECTOR.mojMethod("findEntities", NMS_COMMANDSOURCESTACK));
public static final ReflectMethod<?> NMS_ENTITYSELECTOR_FINDPLAYERS = wrapEx(() -> NMS_ENTITYSELECTOR.mojMethod("findPlayers", NMS_COMMANDSOURCESTACK));
public static final ReflectMethod<?> NMS_ENTITYSELECTOR_FINDSINGLEENTITY = wrapEx(() -> NMS_ENTITYSELECTOR.mojMethod("findSingleEntity", NMS_COMMANDSOURCESTACK));
public static final ReflectMethod<?> NMS_ENTITYSELECTOR_FINDSINGLEPLAYER = wrapEx(() -> NMS_ENTITYSELECTOR.mojMethod("findSinglePlayer", NMS_COMMANDSOURCESTACK));
public static final ClassMapping NMS_ENTITY = wrapEx(() -> NMSReflect.mojClass("net.minecraft.world.entity.Entity"));
public static final ReflectMethod<?> NMS_ENTITY_GETBUKKITENTITY = wrapEx(() -> NMS_ENTITY.runtimeReflect().method("getBukkitEntity"));
public static final ClassMapping NMS_COMPONENTARGUMENT = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.ComponentArgument"));
public static final ReflectConstructor<?> NMS_COMPONENTARGUMENT_CONSTRUCTOR = wrapEx(() -> NMS_COMPONENTARGUMENT.runtimeReflect().constructor());
public static final ClassMapping NMS_BLOCKSTATEARGUMENT = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.blocks.BlockStateArgument"));
public static final ReflectConstructor<?> NMS_BLOCKSTATEARGUMENT_CONSTRUCTOR = wrapEx(() -> NMS_BLOCKSTATEARGUMENT.runtimeReflect().constructor());
public static final ClassMapping NMS_VEC3ARGUMENT = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.coordinates.Vec3Argument"));
public static final ReflectMethod<?> NMS_VEC3ARGUMENT_VEC3 = wrapEx(() -> NMS_VEC3ARGUMENT.mojMethod("vec3", boolean.class));
public static final ClassMapping NMS_COORDINATES = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.coordinates.Coordinates"));
public static final ReflectMethod<?> NMS_COORDINATES_GETPOSITION = wrapEx(() -> NMS_COORDINATES.mojMethod("getPosition", NMS_COMMANDSOURCESTACK));
public static final ReflectMethod<?> NMS_COORDINATES_GETBLOCKPOS = wrapEx(() -> NMS_COORDINATES.mojMethod("getBlockPos", NMS_COMMANDSOURCESTACK));
public static final ClassMapping NMS_BLOCKPOSARGUMENT = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.coordinates.BlockPosArgument"));
public static final ReflectMethod<?> NMS_BLOCKPOSARGUMENT_BLOCKPOS = wrapEx(() -> NMS_BLOCKPOSARGUMENT.mojMethod("blockPos"));
public static final ClassMapping NMS_BLOCKPOS = wrapEx(() -> NMSReflect.mojClass("net.minecraft.core.BlockPos"));
public static final ReflectMethod<?> NMS_BLOCKPOS_GETX = wrapEx(() -> NMS_BLOCKPOS.mojMethod("getX"));
public static final ReflectMethod<?> NMS_BLOCKPOS_GETY = wrapEx(() -> NMS_BLOCKPOS.mojMethod("getY"));
public static final ReflectMethod<?> NMS_BLOCKPOS_GETZ = wrapEx(() -> NMS_BLOCKPOS.mojMethod("getZ"));
public static final ClassMapping NMS_RESOURCELOCATIONARGUMENT = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.ResourceLocationArgument"));
public static final ReflectConstructor<?> NMS_RESOURCELOCATIONARGUMENT_CONSTRUCTOR = wrapEx(() -> NMS_RESOURCELOCATIONARGUMENT.runtimeReflect().constructor());
public static final ClassMapping NMS_RESOURCELOCATION = wrapEx(() -> NMSReflect.mojClass("net.minecraft.resources.ResourceLocation"));
public static final ClassMapping NMS_GAMEPROFILEARGUMENT = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.GameProfileArgument"));
public static final ReflectConstructor<?> NMS_GAMEPROFILEARGUMENT_CONSTRUCTOR = wrapEx(() -> NMS_GAMEPROFILEARGUMENT.runtimeReflect().constructor());
public static final ReflectClass<?> OBC_CRAFTSERVER = wrapEx(() -> OBCReflect.ofClass("CraftServer"));
public static final ReflectMethod<?> OBC_CRAFTSERVER_GETSERVER = wrapEx(() -> OBC_CRAFTSERVER.method("getServer"));
public static final ReflectClass<?> OBC_VANILLACOMMANDWRAPPER = wrapEx(() -> OBCReflect.ofClass("command.VanillaCommandWrapper"));
@SuppressWarnings("unchecked")
public static final ReflectConstructor<? extends Command> OBC_VANILLACOMMANDWRAPPER_CONSTRUCTOR =
(ReflectConstructor<? extends Command>) wrapEx(() -> OBC_VANILLACOMMANDWRAPPER.constructor(
NMS_COMMANDS.runtimeClass(),
CommandNode.class
));
public static final ReflectField<?> OBC_VANILLACOMMANDWRAPPER_VANILLACOMMAND = wrapEx(() -> OBC_VANILLACOMMANDWRAPPER.field("vanillaCommand"));
public static final ReflectMethod<?> OBC_VANILLACOMMANDWRAPPER_GETLISTENER = wrapEx(() -> OBC_VANILLACOMMANDWRAPPER.method("getListener", CommandSender.class));
public static final ReflectClass<?> OBC_CRAFTNAMESPACEDKEY = wrapEx(() -> OBCReflect.ofClass("util.CraftNamespacedKey"));
public static final ReflectMethod<?> OBC_CRAFTNAMESPACEDKEY_TOMINECRAFT = wrapEx(() -> OBC_CRAFTNAMESPACEDKEY.method("toMinecraft", NamespacedKey.class));
public static final ReflectMethod<?> OBC_CRAFTNAMESPACEDKEY_FROMMINECRAFT = wrapEx(() -> OBC_CRAFTNAMESPACEDKEY.method("fromMinecraft", NMS_RESOURCELOCATION.runtimeClass()));
public static final ReflectClass<?> OBC_CRAFTVECTOR = wrapEx(() -> OBCReflect.ofClass("util.CraftVector"));
public static final ReflectMethod<?> OBC_CRAFTVECTOR_TOBUKKIT_VEC3 = wrapEx(() -> OBC_VANILLACOMMANDWRAPPER.method("toBukkit", NMS_VEC3.runtimeClass()));
public static final ReflectClass<?> PAPER_PAPERADVENTURE = wrapEx(() -> Reflect.ofClass("io.papermc.paper.adventure.PaperAdventure"));
public static final ReflectMethod<?> PAPER_PAPERADVENTURE_ASADVENTURE = wrapEx(() -> PAPER_PAPERADVENTURE.method("asAdventure", NMS_COMPONENT.runtimeClass()));
public static final ReflectClass<?> BRIGADIER_COMMANDNODE = Reflect.ofClass(CommandNode.class);
public static final ReflectMethod<?> BRIGADIER_COMMANDNODE_REMOVECOMMAND = wrapEx(() -> BRIGADIER_COMMANDNODE.method("removeCommand", String.class));
private interface SupplierException<T> {
public T get() throws Exception;
public static final class Coordinates {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.coordinates.Coordinates"));
public static final ReflectMethod<?> getPosition = wrapEx(() -> MAPPING.mojMethod("getPosition", CommandSourceStack.MAPPING));
public static final ReflectMethod<?> getBlockPos = wrapEx(() -> MAPPING.mojMethod("getBlockPos", CommandSourceStack.MAPPING));
}
public static final class BlockPosArgument {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.coordinates.BlockPosArgument"));
public static final ReflectMethod<?> blockPos = wrapEx(() -> MAPPING.mojMethod("blockPos"));
}
public static final class BlockPos {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.core.BlockPos"));
public static final ReflectMethod<?> BLOCKPOS_GETX = wrapEx(() -> MAPPING.mojMethod("getX"));
public static final ReflectMethod<?> BLOCKPOS_GETY = wrapEx(() -> MAPPING.mojMethod("getY"));
public static final ReflectMethod<?> BLOCKPOS_GETZ = wrapEx(() -> MAPPING.mojMethod("getZ"));
}
public static final class ResourceLocationArgument {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.ResourceLocationArgument"));
public static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor());
}
public static final class ResourceLocation {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.resources.ResourceLocation"));
}
public static final class GameProfileArgument {
public static final ClassMapping MAPPING = wrapEx(() -> NMSReflect.mojClass("net.minecraft.commands.arguments.GameProfileArgument"));
public static final ReflectConstructor<?> CONSTRUCTOR = wrapEx(() -> MAPPING.runtimeReflect().constructor());
}
}
private static <T> T wrapEx(SupplierException<T> prv) {
public static final class OBC {
public static final class CraftServer {
public static final ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("CraftServer"));
public static final ReflectMethod<?> getServer = wrapEx(() -> REFLECT.method("getServer"));
}
public static final class VanillaCommandWrapper {
public static final ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("command.VanillaCommandWrapper"));
@SuppressWarnings("unchecked")
public static final ReflectConstructor<? extends Command> CONSTRUTOR =
(ReflectConstructor<? extends Command>) wrapEx(() -> REFLECT.constructor(
NMS.Commands.MAPPING.runtimeClass(),
CommandNode.class
));
public static final ReflectField<?> vanillaCommand = wrapEx(() -> REFLECT.field("vanillaCommand"));
public static final ReflectMethod<?> getListener = wrapEx(() -> REFLECT.method("getListener", CommandSender.class));
}
public static final class CraftNamespacedKey {
public static final ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("util.CraftNamespacedKey"));
public static final ReflectMethod<?> toMinecraft = wrapEx(() -> REFLECT.method("toMinecraft", NamespacedKey.class));
public static final ReflectMethod<?> fromMinecraft = wrapEx(() -> REFLECT.method("fromMinecraft", NMS.ResourceLocation.MAPPING.runtimeClass()));
}
public static final class CraftVector {
public static final ReflectClass<?> REFLECT = wrapEx(() -> OBCReflect.ofClass("util.CraftVector"));
public static final ReflectMethod<?> toBukkit_vec3 = wrapEx(() -> REFLECT.method("toBukkit", NMS.Vec3.MAPPING.runtimeClass()));
}
}
public static final class Paper {
public static final class PaperAdventure {
public static final ReflectClass<?> REFLECT = wrapEx(() -> Reflect.ofClass("io.papermc.paper.adventure.PaperAdventure"));
public static final ReflectMethod<?> asAdventure = wrapEx(() -> REFLECT.method("asAdventure", NMS.Component.MAPPING.runtimeClass()));
}
}
public static final class Brigadier {
public static final class CommandNode {
public static final ReflectClass<?> REFLECT = Reflect.ofClass(com.mojang.brigadier.tree.CommandNode.class);
public static final ReflectMethod<?> removeCommand = wrapEx(() -> REFLECT.method("removeCommand", String.class));
}
}
/*
* Initialization stuff
*/
public static void init() {
initRecursively(ReflectRegistry.class);
}
private static void initRecursively(Class<?> cl) {
try {
return prv.get();
} catch (Exception e) {
throw new RuntimeException(e);
Class.forName(cl.getName()); // force initializing the member classes
} catch (ExceptionInInitializerError e) {
Log.severe("Error while initilizing a ReflectRegistry entry at " + cl.getName(), e.getCause());
} catch (NoClassDefFoundError e) {
// if a previously initialized class failed to actually initialize
Log.severe("Error while initilizing a ReflectRegistry entry at " + cl.getName() + " due to a previously failed initialization (" + e.getMessage() + ")");
} catch (ClassNotFoundException e) {
Log.severe("Wut? (should not append)", e);
}
for (Class<?> declaredClass : cl.getDeclaredClasses()) {
initRecursively(declaredClass);
}
}