From b7700ac18778a6e24436cf56e1c80d13b6ec3146 Mon Sep 17 00:00:00 2001 From: Jan Boerman Date: Tue, 10 Sep 2024 00:31:42 +0200 Subject: [PATCH] debug Platform bytecode transformer --- .../scalaloader/compat/Platform.java | 62 ++++++++++++++++++- .../scalaloader/paper/plugin/PaperHacks.java | 4 +- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/ScalaLoader-Common/src/main/java/xyz/janboerman/scalaloader/compat/Platform.java b/ScalaLoader-Common/src/main/java/xyz/janboerman/scalaloader/compat/Platform.java index a8d2b01f..5a04fefe 100644 --- a/ScalaLoader-Common/src/main/java/xyz/janboerman/scalaloader/compat/Platform.java +++ b/ScalaLoader-Common/src/main/java/xyz/janboerman/scalaloader/compat/Platform.java @@ -10,6 +10,8 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.util.Collections; +import java.util.Set; /** * This class is NOT part of the public API! @@ -73,14 +75,65 @@ private CraftBukkitPlatform() {} private MethodHandle commodoreConvert = null; private boolean attempted = false; + public byte[] transformNative(Server craftServer, Class apiVersionClass, byte[] classBytes, ScalaPluginClassLoader pluginClassLoader) throws Throwable { + IScalaLoader.getInstance().getLogger().info("DEBUG: transform native.."); + MethodHandles.Lookup lookup = MethodHandles.lookup(); + if (commodoreConvert == null) { + + IScalaLoader.getInstance().getLogger().info("DEBUG: first attempt to find Commodore#convert!"); + attempted = true; + try { + // public static byte[] convert(byte[] b, final String pluginName, final ApiVersion pluginVersion, final Set activeCompatibilities) + Class commodoreClass = Class.forName(getPackageName(craftServer.getClass()) + ".util.Commodore"); + String methodName = "convert"; + MethodType methodType = MethodType.methodType(byte[].class, + new Class[] { byte[].class, String.class, apiVersionClass, Set.class }); + IScalaLoader.getInstance().getLogger().info("DEBUG: looking up static convert method.."); + commodoreConvert = lookup.findStatic(commodoreClass, methodName, methodType); + IScalaLoader.getInstance().getLogger().info("DEBUG: found commodore convert!"); + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException ignored) { + IScalaLoader.getInstance() + .getLogger() + .info("DEBUG: could not find Commodore#convert!!! " + ignored.getClass().getName() + ": " + + ignored.getMessage()); + //impossible + } + } + + if (commodoreConvert != null) { + IScalaLoader.getInstance().getLogger().info("DEBUG: converting class.."); + String pluginName = pluginClassLoader.getPlugin().getName(); + try { + MethodHandle getOrCreateVersion = lookup.findStatic(apiVersionClass, "getOrCreateVersion", MethodType.methodType(apiVersionClass, String.class)); + Object apiVersion = getOrCreateVersion.invoke(pluginClassLoader.getApiVersion().getVersionString()); + + Set activeCompatibilities = Collections.emptySet(); + try { + MethodHandle compatibilitiesGetter = lookup.findGetter(craftServer.getClass(), "activeCompatibilities", Set.class); + activeCompatibilities = (Set) compatibilitiesGetter.invoke(craftServer); + } catch (Exception couldNotDetermineActiveCompatibilities) { + } + + classBytes = (byte[]) commodoreConvert.invoke(classBytes, pluginName, apiVersion, activeCompatibilities); + IScalaLoader.getInstance().getLogger().info("DEBUG: converted class!"); + } catch (NoSuchMethodException | IllegalAccessException ignored) { + IScalaLoader.getInstance().getLogger().info("DEBUG: could not invoke Commodore#convert!!! " + ignored.getClass().getName() + ": " + ignored.getMessage()); + } + } + + return classBytes; + } + public byte[] transformNative(Server craftServer, byte[] classBytes, boolean modern) throws Throwable { if (!attempted) { attempted = true; MethodHandles.Lookup lookup = MethodHandles.lookup(); try { + // public static byte[] convert(byte[] b, boolean isModern) Class commodoreClass = Class.forName(getPackageName(craftServer.getClass()) + ".util.Commodore"); String methodName = "convert"; - MethodType methodType = MethodType.methodType(byte[].class, new Class[]{byte[].class, boolean.class}); + MethodType methodType = MethodType.methodType(byte[].class, + new Class[] { byte[].class, boolean.class }); commodoreConvert = lookup.findStatic(commodoreClass, methodName, methodType); } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException ignored) { //running on craftbukkit 1.12.2 or earlier @@ -96,7 +149,12 @@ public byte[] transformNative(Server craftServer, byte[] classBytes, boolean mod @Override public byte[] transform(String jarEntryPath, byte[] classBytes, ScalaPluginClassLoader pluginClassLoader) throws Throwable { - return transformNative(pluginClassLoader.getServer(), classBytes, pluginClassLoader.getApiVersion() != ApiVersion.LEGACY); + try { + Class apiVersionClass = Class.forName("org.bukkit.craftbukkit.util.ApiVersion"); + return transformNative(pluginClassLoader.getServer(), apiVersionClass, classBytes, pluginClassLoader); + } catch (ClassNotFoundException e) { + return transformNative(pluginClassLoader.getServer(), classBytes, pluginClassLoader.getApiVersion() != ApiVersion.LEGACY); + } } } diff --git a/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/PaperHacks.java b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/PaperHacks.java index 70e96f57..a24cfdfa 100644 --- a/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/PaperHacks.java +++ b/ScalaLoader-Paper/src/main/java/xyz/janboerman/scalaloader/paper/plugin/PaperHacks.java @@ -4,7 +4,7 @@ import org.bukkit.Bukkit; import org.bukkit.plugin.PluginManager; -public class PaperHacks { +public final class PaperHacks { private PaperHacks() {} @@ -17,6 +17,4 @@ public static PaperPluginManagerImpl getPaperPluginManager() { } } - - }