aboutsummaryrefslogtreecommitdiff
path: root/src/Java/gtPlusPlus/preloader/asm/Preloader_ClassTransformer.java
blob: 330aef318a4cb7a6cf45242b02e644a8b73ece38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package gtPlusPlus.preloader.asm;

import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;

import java.util.Iterator;

import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;

import gtPlusPlus.core.util.Utils;
import net.minecraft.launchwrapper.IClassTransformer;

public class Preloader_ClassTransformer implements IClassTransformer {

	@Override
	public byte[] transform(String name, String transformedName, byte[] basicClass) {

		/*if (name.equals("abq")) {
			Utils.LOG_ASM("[ASM] INSIDE OBFUSCATED EXPLOSION TRANSFORMER ABOUT TO PATCH: " + name);
			return patchClassASM(name, basicClass, true);
		}

		else if (name.equals("net.minecraftforge.oredict.OreDictionary")) {
			Utils.LOG_ASM("[ASM] INSIDE OREDICT TRANSFORMER ABOUT TO PATCH: " + name);
			return patchClassASM(name, basicClass, false);
		}*/
		return basicClass;
	}

	public byte[] patchClassASM(String name, byte[] bytes, boolean obfuscated) {

		String targetMethodName = "";

		if(obfuscated == true)
			targetMethodName ="a";
		else
			targetMethodName ="registerOreImpl";


		//set up ASM class manipulation stuff. Consult the ASM docs for details
		ClassNode classNode = new ClassNode();
		ClassReader classReader = new ClassReader(bytes);
		classReader.accept(classNode, 0);



		//Now we loop over all of the methods declared inside the Explosion class until we get to the targetMethodName "doExplosionB"

		// find method to inject into
		Iterator<MethodNode> methods = classNode.methods.iterator();
		while(methods.hasNext())
		{
			MethodNode m = methods.next();
			Utils.LOG_ASM("[ASM] Method Name: "+m.name + " Desc:" + m.desc);

			//Check if this is doExplosionB and it's method signature is (Z)V which means that it accepts a boolean (Z) and returns a void (V)
			if ((m.name.equals(targetMethodName) && m.desc.equals("(Ljava/lang/String;Lnet/minecraft/item/ItemStack;)V")))
			{
				Utils.LOG_ASM("[ASM] Inside target method!");
				// find interesting instructions in method, there is a single FDIV instruction we use as target
				
				// make new instruction list
				InsnList toInject = new InsnList();

				//toInject.add(new VarInsnNode(ALOAD, 0));
				
				toInject.add(new VarInsnNode(ALOAD, 1));
				toInject.add(new MethodInsnNode(INVOKESTATIC, "gtPlusPlus/preloader/Preloader_GT_OreDict", "removeCircuit", "(Lnet/minecraft/item/ItemStack;)Z, false"));
				toInject.add(new VarInsnNode(Opcodes.IFEQ, 1));
				toInject.add(new VarInsnNode(Opcodes.RETURN, 0));
				//toInject.add(new VarInsnNode(org.objectweb.asm.Opcodes.LABEL END, 0));

				// inject new instruction list into method instruction list
				m.instructions.insert(toInject);

				Utils.LOG_ASM("Patching Complete!");
				break;
			}
		}

		//ASM specific for cleaning up and returning the final bytes for JVM processing.
		ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
		classNode.accept(writer);
		return writer.toByteArray();
	}

}