-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added transformer for onUsingTick in EntityPlayer #414
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package com.mitchej123.hodgepodge.asm.transformers.mc; | ||
|
||
import net.minecraft.launchwrapper.IClassTransformer; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
import org.apache.logging.log4j.Logger; | ||
import org.objectweb.asm.ClassReader; | ||
import org.objectweb.asm.ClassWriter; | ||
import org.objectweb.asm.Opcodes; | ||
import org.objectweb.asm.tree.ClassNode; | ||
import org.objectweb.asm.tree.FieldInsnNode; | ||
import org.objectweb.asm.tree.JumpInsnNode; | ||
import org.objectweb.asm.tree.MethodInsnNode; | ||
|
||
public class EntityPlayerTransformer implements IClassTransformer { | ||
|
||
private static final Logger LOGGER = LogManager.getLogger("EntityPlayerTransformer"); | ||
|
||
@Override | ||
public byte[] transform(String name, String transformedName, byte[] basicClass) { | ||
if (basicClass == null) return null; | ||
|
||
if (NameContext.Obf.entityPlayer.equals(name)) { | ||
final ClassReader cr = new ClassReader(basicClass); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. write the class reader code once for both classes |
||
final ClassNode cn = new ClassNode(); | ||
cr.accept(cn, 0); | ||
transformClassNode(NameContext.Obf, cn); | ||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); | ||
cn.accept(cw); | ||
|
||
LOGGER.info("Transformed {}", name); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you don't need to log that you are transforming a class, however you should use a try catch and if it returns an exception, you should log it and return the untransformed class |
||
return cw.toByteArray(); | ||
} | ||
|
||
if (NameContext.Deobf.entityPlayer.equals(name)) { | ||
final ClassReader cr = new ClassReader(basicClass); | ||
final ClassNode cn = new ClassNode(); | ||
cr.accept(cn, 0); | ||
transformClassNode(NameContext.Deobf, cn); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't do that to check the obfuscation state, check it from the injectData method in the |
||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); | ||
cn.accept(cw); | ||
|
||
LOGGER.info("Transformed {}", name); | ||
return cw.toByteArray(); | ||
} | ||
|
||
return basicClass; | ||
} | ||
|
||
public void transformClassNode(NameContext names, ClassNode cn) { | ||
LOGGER.info("Found EntityPlayer (class = {}, name context = {})", names.entityPlayer, names.name()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't need to log |
||
|
||
for (var method : cn.methods) { | ||
if (method.name.equals(names.onUpdate)) { | ||
LOGGER.info("Found EntityPlayer.onUpdate ({})", names.onUpdate); | ||
|
||
var cursor = method.instructions.getFirst(); | ||
|
||
while (cursor != null) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why don't you use the built in iterator or a for loop over instructions.toArray() |
||
if (cursor instanceof FieldInsnNode field && field.getOpcode() == Opcodes.GETFIELD | ||
&& field.name.equals(names.itemInUse)) { | ||
if (cursor.getNext() instanceof JumpInsnNode jump && jump.getOpcode() == Opcodes.IF_ACMPNE) { | ||
LOGGER.info("Found injection point"); | ||
|
||
method.instructions.insertBefore( | ||
jump, | ||
new MethodInsnNode( | ||
Opcodes.INVOKESTATIC, | ||
names.itemStack, | ||
names.areItemStacksEqual, | ||
String.format("(L%s;L%s;)Z", names.itemStack, names.itemStack), | ||
false)); | ||
|
||
((JumpInsnNode) jump).setOpcode(Opcodes.IFEQ); | ||
return; | ||
} | ||
} | ||
|
||
cursor = cursor.getNext(); | ||
} | ||
|
||
LOGGER.warn("Could not find injection point."); | ||
} | ||
} | ||
} | ||
|
||
private static enum NameContext { | ||
|
||
Deobf("net.minecraft.entity.player.EntityPlayer", "onUpdate", "net/minecraft/item/ItemStack", | ||
"areItemStacksEqual", "itemInUse"), | ||
Obf("yz", "h", "add", "b", "f"); | ||
|
||
public final String entityPlayer, onUpdate, itemStack, areItemStacksEqual, itemInUse; | ||
|
||
private NameContext(String entityPlayer, String onUpdate, String itemStack, String areItemStacksEqual, | ||
String itemInUse) { | ||
this.entityPlayer = entityPlayer; | ||
this.onUpdate = onUpdate; | ||
this.itemStack = itemStack; | ||
this.areItemStacksEqual = areItemStacksEqual; | ||
this.itemInUse = itemInUse; | ||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can check
transformedName
directly, it won't be obfuscatedThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested it in the full pack and it looks like this isn't the case. I had to use the obfuscated name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can do
"net.minecraft.entity.player.EntityPlayer".equals(transformedName)
even when in obfuscated environement