10
10
import java .lang .invoke .MethodHandle ;
11
11
import java .lang .invoke .MethodHandles ;
12
12
import java .lang .invoke .MethodType ;
13
+ import java .util .Collections ;
14
+ import java .util .Set ;
13
15
14
16
/**
15
17
* This class is NOT part of the public API!
16
18
*/
17
19
public class Platform {
18
20
21
+ private static final String FAKE_PLUGIN_NAME = "Fake" ;
22
+
19
23
protected Platform () {
20
24
}
21
25
@@ -31,7 +35,7 @@ public <ScalaPluginClassLoader extends ClassLoader & IScalaPluginClassLoader> by
31
35
try {
32
36
Server server = currentPluginClassLoader .getServer ();
33
37
UnsafeValues unsafeValues = server .getUnsafe ();
34
- String fakeDescription = "name: Fake" + System .lineSeparator () +
38
+ String fakeDescription = "name: " + FAKE_PLUGIN_NAME + System .lineSeparator () +
35
39
"version: 1.0" + System .lineSeparator () +
36
40
"main: xyz.janboerman.scalaloader.FakePlugin" + System .lineSeparator ();
37
41
ApiVersion apiVersion = currentPluginClassLoader .getApiVersion ();
@@ -68,19 +72,69 @@ public static Platform detect(Server server) {
68
72
69
73
public static class CraftBukkitPlatform extends Platform {
70
74
75
+ private static final Class <?> API_VERSION_CLASS ;
76
+ static {
77
+ Class <?> apiVersionClass ;
78
+ try {
79
+ apiVersionClass = Class .forName ("org.bukkit.craftbukkit.util.ApiVersion" );
80
+ } catch (ClassNotFoundException e ) {
81
+ apiVersionClass = null ;
82
+ }
83
+ API_VERSION_CLASS = apiVersionClass ;
84
+ }
85
+
71
86
private CraftBukkitPlatform () {}
72
87
73
88
private MethodHandle commodoreConvert = null ;
74
89
private boolean attempted = false ;
75
90
91
+ public <ScalaPluginClassLoader extends ClassLoader & IScalaPluginClassLoader > byte [] transformNative (Server craftServer , byte [] classBytes , ScalaPluginClassLoader pluginClassLoader ) throws Throwable {
92
+ MethodHandles .Lookup lookup = MethodHandles .lookup ();
93
+ if (commodoreConvert == null ) {
94
+ attempted = true ;
95
+ try {
96
+ // public static byte[] convert(byte[] b, final String pluginName, final ApiVersion pluginVersion, final Set<String> activeCompatibilities)
97
+ Class <?> commodoreClass = Class .forName (getPackageName (craftServer .getClass ()) + ".util.Commodore" );
98
+ String methodName = "convert" ;
99
+ MethodType methodType = MethodType .methodType (byte [].class ,
100
+ new Class <?>[] { byte [].class , String .class , API_VERSION_CLASS , Set .class });
101
+ commodoreConvert = lookup .findStatic (commodoreClass , methodName , methodType );
102
+ } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException ignored ) {
103
+ //impossible
104
+ }
105
+ }
106
+
107
+ if (commodoreConvert != null ) {
108
+ String pluginName = getPluginName (pluginClassLoader );
109
+ try {
110
+ MethodHandle getOrCreateVersion = lookup .findStatic (API_VERSION_CLASS , "getOrCreateVersion" , MethodType .methodType (API_VERSION_CLASS , String .class ));
111
+ Object apiVersion = getOrCreateVersion .invoke (pluginClassLoader .getApiVersion ().getVersionString ());
112
+
113
+ Set activeCompatibilities = Collections .emptySet ();
114
+ try {
115
+ MethodHandle compatibilitiesGetter = lookup .findGetter (craftServer .getClass (), "activeCompatibilities" , Set .class );
116
+ activeCompatibilities = (Set ) compatibilitiesGetter .invoke (craftServer );
117
+ } catch (Exception couldNotDetermineActiveCompatibilities ) {
118
+ }
119
+
120
+ classBytes = (byte []) commodoreConvert .invoke (classBytes , pluginName , apiVersion , activeCompatibilities );
121
+ } catch (NoSuchMethodException | IllegalAccessException ignored ) {
122
+ }
123
+ }
124
+
125
+ return classBytes ;
126
+ }
127
+
76
128
public byte [] transformNative (Server craftServer , byte [] classBytes , boolean modern ) throws Throwable {
77
129
if (!attempted ) {
78
130
attempted = true ;
79
131
MethodHandles .Lookup lookup = MethodHandles .lookup ();
80
132
try {
133
+ // public static byte[] convert(byte[] b, boolean isModern)
81
134
Class <?> commodoreClass = Class .forName (getPackageName (craftServer .getClass ()) + ".util.Commodore" );
82
135
String methodName = "convert" ;
83
- MethodType methodType = MethodType .methodType (byte [].class , new Class <?>[]{byte [].class , boolean .class });
136
+ MethodType methodType = MethodType .methodType (byte [].class ,
137
+ new Class <?>[] { byte [].class , boolean .class });
84
138
commodoreConvert = lookup .findStatic (commodoreClass , methodName , methodType );
85
139
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException ignored ) {
86
140
//running on craftbukkit 1.12.2 or earlier
@@ -96,9 +150,21 @@ public byte[] transformNative(Server craftServer, byte[] classBytes, boolean mod
96
150
97
151
@ Override
98
152
public <ScalaPluginClassLoader extends ClassLoader & IScalaPluginClassLoader > byte [] transform (String jarEntryPath , byte [] classBytes , ScalaPluginClassLoader pluginClassLoader ) throws Throwable {
99
- return transformNative (pluginClassLoader .getServer (), classBytes , pluginClassLoader .getApiVersion () != ApiVersion .LEGACY );
153
+ if (API_VERSION_CLASS != null ) {
154
+ return transformNative (pluginClassLoader .getServer (), classBytes , pluginClassLoader );
155
+ } else {
156
+ return transformNative (pluginClassLoader .getServer (), classBytes , pluginClassLoader .getApiVersion () != ApiVersion .LEGACY );
157
+ }
100
158
}
101
159
160
+ private static String getPluginName (IScalaPluginClassLoader classLoader ) {
161
+ IScalaPlugin plugin = classLoader .getPlugin ();
162
+ if (plugin == null ) {
163
+ return FAKE_PLUGIN_NAME ;
164
+ } else {
165
+ return plugin .getName ();
166
+ }
167
+ }
102
168
}
103
169
104
170
public static class GlowstonePlatform extends Platform {
0 commit comments