22
33import cn .apisium .papershelled .services .MixinService ;
44import com .google .common .io .ByteStreams ;
5+ import org .checkerframework .checker .units .qual .C ;
56import org .jetbrains .annotations .NotNull ;
67import org .jetbrains .annotations .Nullable ;
78import org .objectweb .asm .*;
2829import java .util .Objects ;
2930import java .util .jar .JarEntry ;
3031import java .util .jar .JarFile ;
31- import java .util .logging .* ;
32+ import java .util .logging .Logger ;
3233
3334public final class PaperShelledAgent {
3435 private static boolean initialized ;
@@ -61,10 +62,12 @@ public String map(String name) {
6162
6263 @ Nullable
6364 public static InputStream getResourceAsStream (String name ) { return ClassLoader .getSystemResourceAsStream (name ); }
65+
6466 @ Nullable
6567 public static InputStream getClassAsStream (String name ) {
6668 return getResourceAsStream (name .replace ('.' , '/' ) + ".class" );
6769 }
70+
6871 public static byte [] getClassAsByteArray (String name ) throws IOException {
6972 try (InputStream is = getClassAsStream (name )) {
7073 if (is == null ) throw new FileNotFoundException ("Class not found: " + name );
@@ -76,9 +79,50 @@ private final static class Transformer implements ClassFileTransformer {
7679 @ Override
7780 public byte [] transform (ClassLoader loader , String className , Class <?> classBeingRedefined ,
7881 ProtectionDomain protectionDomain , byte [] data ) {
79- if ("org/bukkit/craftbukkit/Main" .equals (className )) {
82+ if ("io/papermc/paperclip/Paperclip" .equals (className )) {
83+ ClassReader cr = new ClassReader (data );
84+ ClassWriter cw = new ClassWriter (ClassWriter .COMPUTE_MAXS );
85+ cr .accept (new ClassVisitor (Opcodes .ASM9 , cw ) {
86+ @ Override
87+ public MethodVisitor visitMethod (int access , String name , String descriptor , String signature , String [] exceptions ) {
88+ MethodVisitor v = super .visitMethod (access , name , descriptor , signature , exceptions );
89+ return name .equals ("main" ) ? new MethodVisitor (Opcodes .ASM9 ) {
90+ /**
91+ * What I want is as follows:
92+ * {@code
93+ *
94+ * public static void main(String[] args){
95+ * cn.apisium.papershelled.launcher.Launcher.launch(args);
96+ * }
97+ *
98+ * }
99+ * And this is the ASM way to make it.
100+ */
101+ @ Override
102+ public void visitCode () {
103+ super .visitCode ();
104+ Label l0 = new Label ();
105+ v .visitLabel (l0 );
106+ v .visitLineNumber (0 , l0 );//Trick JVM
107+ v .visitVarInsn (Opcodes .ALOAD , 0 );
108+ v .visitMethodInsn (Opcodes .INVOKESTATIC , "cn/apisium/papershelled/launcher/Launcher" , "launch" , "([Ljava/lang/String;)V" , false );
109+ Label l1 = new Label ();
110+ v .visitLabel (l1 );
111+ v .visitLineNumber (0 , l1 );
112+ v .visitInsn (Opcodes .RETURN );
113+ Label l2 = new Label ();
114+ v .visitLabel (l2 );
115+ v .visitLocalVariable ("args" , "[Ljava/lang/String;" , null , l0 , l2 , 0 );
116+ v .visitMaxs (1 , 1 );
117+ v .visitEnd ();
118+ }
119+ } : v ;
120+ }
121+ }, ClassReader .EXPAND_FRAMES );
122+ return cw .toByteArray ();
123+ } else if ("org/bukkit/craftbukkit/Main" .equals (className )) {
80124 data = inject (data , "main" , "cn/apisium/papershelled/PaperShelledAgent" , "init" );
81- URL url = Objects .requireNonNull (ClassLoader . getSystemResource ("org/bukkit/craftbukkit/Main.class" ));
125+ URL url = Objects .requireNonNull (loader . getResource ("org/bukkit/craftbukkit/Main.class" ));
82126 try {
83127 serverJar = Paths .get (new URI (url .getFile ().split ("!" , 2 )[0 ]));
84128 } catch (URISyntaxException e ) {
0 commit comments