Skip to content

Commit

Permalink
Cleanup transformer
Browse files Browse the repository at this point in the history
  • Loading branch information
prplz committed Nov 27, 2017
1 parent c19d5bc commit ca7fcf1
Showing 1 changed file with 54 additions and 70 deletions.
124 changes: 54 additions & 70 deletions src/main/java/io/prplz/memoryfix/ClassTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.objectweb.asm.tree.MethodNode;

import java.util.Iterator;
import java.util.function.BiConsumer;

public class ClassTransformer implements IClassTransformer {

Expand All @@ -22,14 +23,27 @@ public byte[] transform(String name, String transformedName, byte[] bytes) {
return transformCapeUtils(bytes);
} else if (name.equals("io.prplz.memoryfix.CapeImageBuffer")) {
// Redirect our stub calls to optifine
return transformCapeImageBuffer(bytes);
return transformMethods(bytes, this::transformCapeImageBuffer);
} else if (transformedName.equals("net.minecraft.client.resources.AbstractResourcePack")) {
return transformAbstractResourcePack(bytes);
return transformMethods(bytes, this::transformAbstractResourcePack);
} else if (transformedName.equals("net.minecraft.client.Minecraft")) {
// Remove System.gc calls (they all happen in this class)
return transformMinecraft(bytes);
return transformMethods(bytes, this::transformMinecraft);
} else {
return bytes;
}
return bytes;
}

private byte[] transformMethods(byte[] bytes, BiConsumer<ClassNode, MethodNode> transformer) {
ClassReader classReader = new ClassReader(bytes);
ClassNode classNode = new ClassNode();
classReader.accept(classNode, ClassReader.EXPAND_FRAMES);

classNode.methods.forEach(m -> transformer.accept(classNode, m));

ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classNode.accept(classWriter);
return classWriter.toByteArray();
}

private byte[] transformCapeUtils(byte[] bytes) {
Expand All @@ -50,84 +64,54 @@ public String map(String typeName) {
return classWriter.toByteArray();
}

private byte[] transformCapeImageBuffer(byte[] bytes) {
ClassReader classReader = new ClassReader(bytes);
ClassNode classNode = new ClassNode();
classReader.accept(classNode, ClassReader.EXPAND_FRAMES);

for (MethodNode method : classNode.methods) {
Iterator<AbstractInsnNode> iter = method.instructions.iterator();
while (iter.hasNext()) {
AbstractInsnNode insn = iter.next();
if (insn instanceof MethodInsnNode) {
MethodInsnNode methodInsn = (MethodInsnNode) insn;
if (methodInsn.name.equals("parseCape")) {
methodInsn.owner = "CapeUtils";
} else if (methodInsn.name.equals("setLocationOfCape")) {
methodInsn.setOpcode(Opcodes.INVOKEVIRTUAL);
methodInsn.owner = "net/minecraft/client/entity/AbstractClientPlayer";
methodInsn.desc = "(Lnet/minecraft/util/ResourceLocation;)V";
}
private void transformCapeImageBuffer(ClassNode clazz, MethodNode method) {
Iterator<AbstractInsnNode> iter = method.instructions.iterator();
while (iter.hasNext()) {
AbstractInsnNode insn = iter.next();
if (insn instanceof MethodInsnNode) {
MethodInsnNode methodInsn = (MethodInsnNode) insn;
if (methodInsn.name.equals("parseCape")) {
methodInsn.owner = "CapeUtils";
} else if (methodInsn.name.equals("setLocationOfCape")) {
methodInsn.setOpcode(Opcodes.INVOKEVIRTUAL);
methodInsn.owner = "net/minecraft/client/entity/AbstractClientPlayer";
methodInsn.desc = "(Lnet/minecraft/util/ResourceLocation;)V";
}
}
}

ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classNode.accept(classWriter);
return classWriter.toByteArray();
}

private byte[] transformAbstractResourcePack(byte[] bytes) {
ClassReader classReader = new ClassReader(bytes);
ClassNode classNode = new ClassNode();
classReader.accept(classNode, ClassReader.EXPAND_FRAMES);

for (MethodNode method : classNode.methods) {
if (DeobfUtil.matchMethod(
classNode,
method,
"func_110586_a",
"getPackImage",
"()Ljava/awt/image/BufferedImage;")) {
Iterator<AbstractInsnNode> iter = method.instructions.iterator();
while (iter.hasNext()) {
AbstractInsnNode insn = iter.next();
if (insn.getOpcode() == Opcodes.ARETURN) {
method.instructions.insertBefore(insn, new MethodInsnNode(
Opcodes.INVOKESTATIC,
"io.prplz.memoryfix.ResourcePackImageScaler".replace('.', '/'),
"scalePackImage",
"(Ljava/awt/image/BufferedImage;)Ljava/awt/image/BufferedImage;"));
}
private void transformAbstractResourcePack(ClassNode clazz, MethodNode method) {
if (DeobfUtil.matchMethod(
clazz,
method,
"func_110586_a",
"getPackImage",
"()Ljava/awt/image/BufferedImage;")) {
Iterator<AbstractInsnNode> iter = method.instructions.iterator();
while (iter.hasNext()) {
AbstractInsnNode insn = iter.next();
if (insn.getOpcode() == Opcodes.ARETURN) {
method.instructions.insertBefore(insn, new MethodInsnNode(
Opcodes.INVOKESTATIC,
"io.prplz.memoryfix.ResourcePackImageScaler".replace('.', '/'),
"scalePackImage",
"(Ljava/awt/image/BufferedImage;)Ljava/awt/image/BufferedImage;"));
}
}
}

ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classNode.accept(classWriter);
return classWriter.toByteArray();
}

private byte[] transformMinecraft(byte[] bytes) {
ClassReader classReader = new ClassReader(bytes);
ClassNode classNode = new ClassNode();
classReader.accept(classNode, ClassReader.EXPAND_FRAMES);

for (MethodNode method : classNode.methods) {
Iterator<AbstractInsnNode> iter = method.instructions.iterator();
while (iter.hasNext()) {
AbstractInsnNode insn = iter.next();
if (insn.getOpcode() == Opcodes.INVOKESTATIC) {
MethodInsnNode methodInsn = (MethodInsnNode) insn;
if (methodInsn.owner.equals("java/lang/System") && methodInsn.name.equals("gc")) {
iter.remove();
}
private void transformMinecraft(ClassNode clazz, MethodNode method) {
Iterator<AbstractInsnNode> iter = method.instructions.iterator();
while (iter.hasNext()) {
AbstractInsnNode insn = iter.next();
if (insn.getOpcode() == Opcodes.INVOKESTATIC) {
MethodInsnNode methodInsn = (MethodInsnNode) insn;
if (methodInsn.owner.equals("java/lang/System") && methodInsn.name.equals("gc")) {
iter.remove();
}
}
}

ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classNode.accept(classWriter);
return classWriter.toByteArray();
}
}

0 comments on commit ca7fcf1

Please sign in to comment.