11package ofdev .launchwrapper ;
22
33import static java .lang .reflect .Modifier .isPrivate ;
4+ import net .minecraft .launchwrapper .LaunchClassLoader ;
45import static org .objectweb .asm .Opcodes .ACC_FINAL ;
56import static org .objectweb .asm .Opcodes .ACC_PRIVATE ;
67import static org .objectweb .asm .Opcodes .ACC_PROTECTED ;
3738import java .util .HashMap ;
3839import java .util .HashSet ;
3940import java .util .Iterator ;
41+ import java .util .List ;
4042import java .util .Map ;
4143import java .util .Set ;
44+ import java .util .stream .Collectors ;
4245import java .util .stream .Stream ;
4346
4447// this is needed only in dev environment to get deobfuscated version of OptiFine running
@@ -47,6 +50,8 @@ public class OptifineDevTransformerWrapper implements IClassTransformer {
4750 private static final Path MC_JAR ;
4851 private static final FileSystem mcJarFs ;
4952
53+ private static final List <IClassTransformer > transformers ;
54+
5055 static {
5156 try {
5257 Map <String , String > launchArgs = (Map <String , String >) Launch .blackboard .get ("launchArgs" );
@@ -56,6 +61,10 @@ public class OptifineDevTransformerWrapper implements IClassTransformer {
5661 MC_JAR = Utils .findMinecraftJar (mcGradleCacheDir );
5762 mcJarFs = FileSystems .newFileSystem (MC_JAR , Launch .classLoader );
5863 Launch .classLoader .addURL (MC_JAR .toUri ().toURL ());
64+
65+
66+ transformers = Utils .getFieldValue (LaunchClassLoader .class , Launch .classLoader , "transformers" );
67+
5968 } catch (IOException e ) {
6069 throw new UncheckedIOException (e );
6170 }
@@ -78,9 +87,13 @@ public class OptifineDevTransformerWrapper implements IClassTransformer {
7887 // let it crash
7988 return null ;
8089 }
90+ if (name .equals ("cpw.mods.fml.common.Loader" )) {
91+ return injectCallbackForCodechickenAsm (basicClass );
92+ }
8193
8294 try {
83- boolean isOptifineClass = Stream .of ("optifine." , "net.minecraft." , "net.minecraftforge." , "net.optifine." ).anyMatch (name ::startsWith )
95+ boolean isOptifineClass =
96+ Stream .of ("optifine." , "net.minecraft." , "net.minecraftforge." , "net.optifine." , "shadersmod." ).anyMatch (name ::startsWith )
8497 || !name .contains ("." );
8598 if (!isOptifineClass ) {
8699 return basicClass ;
@@ -116,7 +129,8 @@ public class OptifineDevTransformerWrapper implements IClassTransformer {
116129 ofTransformedDeobfNode .accept (classWriter );
117130 byte [] output = classWriter .toByteArray ();
118131
119- if (isModified .get () || (!transformedName .contains ("." ) || transformedName .startsWith ("optifine" ) || transformedName .startsWith ("net.optifine" ))) {
132+ if (isModified .get () || (!transformedName .contains ("." ) ||
133+ transformedName .startsWith ("shadersmod." ) || transformedName .startsWith ("optifine" ) || transformedName .startsWith ("net.optifine" ))) {
120134 Utils .dumpBytecode (OptifineDevTweakerWrapper .CLASS_DUMP_LOCATION , transformedName , output );
121135 }
122136 return output ;
@@ -125,6 +139,40 @@ public class OptifineDevTransformerWrapper implements IClassTransformer {
125139 }
126140 }
127141
142+ private byte [] injectCallbackForCodechickenAsm (byte [] basicClass ) {
143+ ClassNode cn = new ClassNode ();
144+ ClassReader cr = new ClassReader (basicClass );
145+ cr .accept (cn , 0 );
146+
147+ MethodNode clinit = cn .methods .stream ().filter (m ->m .name .equals ("<clinit>" )).findFirst ()
148+ .orElseThrow (()->new RuntimeException ("No <clinit>" ));
149+ InsnList instructions = clinit .instructions ;
150+ instructions .insert (instructions .get (0 ), new MethodInsnNode (
151+ Opcodes .INVOKESTATIC ,
152+ "ofdev/launchwrapper/OptifineDevTransformerWrapper" ,
153+ "applyTransformerOrder" ,
154+ "()V" , false ));
155+ ClassWriter cw = new ClassWriter (0 );
156+ cn .accept (cw );
157+ return cw .toByteArray ();
158+ }
159+
160+ public static void applyTransformerOrder () {
161+ if (!transformers .get (0 ).getClass ().getName ().equals ("ofdev.launchwrapper.OptifineDevTweakerWrapper$OptiFineTransformerTransformer" )) {
162+ for (int i = 0 ; i < transformers .size (); i ++) {
163+ if (transformers .get (i ).getClass ().getName ().equals ("ofdev.launchwrapper.OptifineDevTweakerWrapper$OptiFineTransformerTransformer" )) {
164+ IClassTransformer rem = transformers .remove (i );
165+ transformers .add (0 , rem );
166+ }
167+ if (transformers .get (i ).getClass ().getName ().equals ("ofdev.launchwrapper.OptifineDevTransformerWrapper" )) {
168+ IClassTransformer rem = transformers .remove (i );
169+ transformers .add (1 , rem );
170+ }
171+ }
172+ assert transformers .get (0 ).getClass ().getName ().equals ("ofdev.launchwrapper.OptifineDevTweakerWrapper$OptiFineTransformerTransformer" );
173+ }
174+ }
175+
128176 private void remapEntityUtils (ClassNode ofTransformedDeobfNode ) {
129177 MethodNode clinit = ofTransformedDeobfNode .methods .stream ().filter (m ->m .name .equals ("<clinit>" )).findFirst ()
130178 .orElseThrow (()->new RuntimeException ("No <clinit>" ));
@@ -274,7 +322,9 @@ private ClassNode toDeobfClassNode(byte[] code) {
274322 Remapper videoSettingsFixer = new Remapper () {
275323 @ Override
276324 public String mapFieldName (String owner , String name , String desc ) {
277- if ((owner .startsWith ("optifine" ) || owner .startsWith ("shadersmod" ) || owner .equals ("net/minecraft/client/gui/GuiVideoSettings" ) || owner .equals ("bef" )) && name .equals ("fontRendererObj" )) {
325+ if ((owner .startsWith ("optifine" ) ||
326+ owner .startsWith ("shadersmod" ) || owner .equals ("net/minecraft/client/gui/GuiVideoSettings" )
327+ || owner .equals ("bef" )) && name .equals ("fontRendererObj" )) {
278328 return "fontRendererObj_OF" ;
279329 }
280330 return super .mapFieldName (owner , name , desc );
@@ -287,7 +337,8 @@ public String mapFieldName(String owner, String name, String desc) {
287337 }
288338
289339 private byte [] getOptifineTransformedBytecode (String name , byte [] basicClass , String notchName , byte [] vanillaCode , Mutable <Boolean > isModified ) {
290- byte [] ofTransformedCode = name .startsWith ("optifine" ) ? vanillaCode : ofTransformer .transform (notchName , notchName , vanillaCode );
340+ byte [] ofTransformedCode = name .startsWith ("optifine" ) || name .startsWith ("shadersmod" ) ? vanillaCode : ofTransformer .transform (notchName ,
341+ notchName , vanillaCode );
291342
292343 if (ofTransformedCode == vanillaCode ) {
293344 ofTransformedCode = basicClass ;
0 commit comments