package denoflionsx.DenPipes.Core.ASM;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.ClassNode;
public class BCHooks implements Opcodes, IClassTransformer {
public static final boolean debugMode = false;
static{
File f = new File("injected");
if (f.exists()){
f.delete();
}
}
@Override
public byte[] transform(String string, String string1, byte[] bytes) {
if (string.equals("buildcraft.transport.pipes.PipePowerWood")) {
bytes = this.injectHook2(bytes, string);
this.printConfirmation(string);
}
if (string.equals("buildcraft.transport.pipes.PipeFluidsWood")) {
bytes = this.injectHook(bytes, string);
this.printConfirmation(string);
}
return bytes;
}
private void printConfirmation(String string) {
System.out.println("[DenPipesCore]: " + "Injected hook(s) into BuildCraft class " + string + "!");
}
public byte[] injectHook(byte[] bytes, String clazz) {
try {
ClassNode cnode = createClassNode(bytes);
MethodVisitor mv = cnode.visitMethod(ACC_PUBLIC, "getPowerHandler", "()Lbuildcraft/api/power/PowerHandler;", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, clazz.replace(".", "/"), "powerHandler", "Lbuildcraft/api/power/PowerHandler;");
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 0);
bytes = createBytes(cnode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
if (debugMode) {
File outDir = new File("injected");
outDir.mkdirs();
dumpClass(outDir, bytes, clazz + "_hook1.class");
}
return bytes;
} catch (Throwable x) {
x.printStackTrace();
}
return bytes;
}
public byte[] injectHook2(byte[] bytes, String clazz) {
try {
ClassNode cnode = createClassNode(bytes);
MethodVisitor mv = cnode.visitMethod(ACC_PUBLIC, "getPowerHandler", "()Lbuildcraft/api/power/PowerHandler;", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, clazz.replace(".", "/"), "powerHandler", "Lbuildcraft/api/power/PowerHandler;");
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 0);
mv = cnode.visitMethod(ACC_PUBLIC, "getPowerSources", "()[Z", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, clazz.replace(".", "/"), "powerSources", "[Z");
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 0);
bytes = createBytes(cnode, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
if (debugMode) {
File outDir = new File("injected");
outDir.mkdirs();
dumpClass(outDir, bytes, clazz + "_hook2.class");
}
return bytes;
} catch (Throwable t) {
t.printStackTrace();
}
return bytes;
}
public static void dumpClass(File outDir, byte[] bytes, String name) {
try {
DataOutputStream out = new DataOutputStream(new FileOutputStream(new File(outDir, name)));
out.write(bytes);
out.flush();
out.close();
} catch (Throwable t) {
}
}
// These methods shamelessly stolen from CodeChicken. You rock at ASM dude.
public static ClassNode createClassNode(byte[] bytes) {
return createClassNode(bytes, 0);
}
public static ClassNode createClassNode(byte[] bytes, int flags) {
ClassNode cnode = new ClassNode();
ClassReader reader = new ClassReader(bytes);
reader.accept(cnode, flags);
return cnode;
}
public static byte[] createBytes(ClassNode cnode, int flags) {
ClassWriter cw = new ClassWriter(flags);
cnode.accept(cw);
return cw.toByteArray();
}
}