本帖最后由 youyihj 于 2023-1-9 10:33 编辑
mojang 判断 UUID 相等居然用 == 的(
1.12.2 ItemStack 的 getTooltip 方法。
用 ASM 也能接受
mojang 判断 UUID 相等居然用 == 的(

1.12.2 ItemStack 的 getTooltip 方法。
用 ASM 也能接受
本帖最后由 gooding300 于 2023-1-9 14:03 编辑
思路就是把if_acmpne改成ifeq再在前面加一个invokestatic java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z。
ASM的话,比较简单的办法是用TreeAPI,具体来说先拿到ItemStack的getTooltip方法的MethodNode,遍历instruments找到if_acmpne,然后判断一下上面2个instruments有没有invokevirtual net.minecraft.entity.ai.attributes.getID ()Ljava/util/UUID;,有的话就把指令替换成ifeq(跳转地址不变),再在前面加一个invokestatic java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z。
因为涉及到上下文关系,用CoreAPI没想到有什么比较干净的办法,等其他大佬的解答。
我的Mixin水平你也知道.jpg
Mixin的话有人写了可以戳我一下。
适用于1.12.2的CoreMod教程,有帮助的话可以点个star:https://github.com/xfl03/CoreModTutor/blob/master/book/4.2.md
思路就是把if_acmpne改成ifeq再在前面加一个invokestatic java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z。
ASM的话,比较简单的办法是用TreeAPI,具体来说先拿到ItemStack的getTooltip方法的MethodNode,遍历instruments找到if_acmpne,然后判断一下上面2个instruments有没有invokevirtual net.minecraft.entity.ai.attributes.getID ()Ljava/util/UUID;,有的话就把指令替换成ifeq(跳转地址不变),再在前面加一个invokestatic java/util/Objects.equals:(Ljava/lang/Object;Ljava/lang/Object;)Z。
因为涉及到上下文关系,用CoreAPI没想到有什么比较干净的办法,等其他大佬的解答。
我的Mixin水平你也知道.jpg
Mixin的话有人写了可以戳我一下。
适用于1.12.2的CoreMod教程,有帮助的话可以点个star:https://github.com/xfl03/CoreModTutor/blob/master/book/4.2.md
gooding300 发表于 2023-1-9 11:43
思路就是把if_acmpne改成ifeq再在前面加一个invokestatic java/util/Objects.equals:(Ljava/lang/Object;Lj ...
我是sb,为什么以前我连equals都不知道

- var Opcodes = Java.type('org.objectweb.asm.Opcodes');
- var MethodInsnNode = Java.type('org.objectweb.asm.tree.MethodInsnNode');
- var InsnNode = Java.type('org.objectweb.asm.tree.InsnNode');
- function initializeCoreMod() {
- return {
- 'uuid': {
- 'target': {
- 'type': 'METHOD',
- 'class': 'net.minecraft.item.ItemStack',
- 'methodName': 'func_82840_a',
- 'methodDesc': '(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/client/util/ITooltipFlag;)Ljava/util/List;'
- },
- 'transformer': function(node) {
- node.maxStack+=2;
- var flag=0;
- var arrayLength = node.instructions.size();
- for (var i = 0; i < arrayLength; ++i) {
- if (node.instructions.get(i).getOpcode() == Opcodes.INVOKEVIRTUAL)
- if (node.instructions.get(i).name == "func_111167_a"){
- flag++;
- node.instructions.insert(node.instructions.get(i),new MethodInsnNode(Opcodes.INVOKEVIRTUAL,"java/util/UUID","getLeastSignificantBits","()J"));
- node.instructions.insert(node.instructions.get(i+2),new MethodInsnNode(Opcodes.INVOKEVIRTUAL,"java/util/UUID","getLeastSignificantBits","()J"));
- node.instructions.get(i+4).setOpcode(Opcodes.IFNE);
- node.instructions.insertBefore(node.instructions.get(i+4),new InsnNode(Opcodes.LCMP));
- if(flag==2)break;
- }
- }
- return node;
- }
- }
- };
- }
- ''
无敌三脚猫 发表于 2023-1-9 17:45
我是sb,为什么以前我连equals都不知道我以前写的是在getID()后面,以及getID()后面的后面,加上getLeast ...
也算是个办法,就是如果getID()有别的用途的话(比如不只是用来比较的话),可能会出问题
gooding300 发表于 2023-1-9 11:43
思路就是把if_acmpne改成ifeq再在前面加一个invokestatic java/util/Objects.equals:(Ljava/lang/Object;Lj ...
我 Mixin 就看你的教程学的,ASM 你教程没写,催更

后来我就用 ASM Core API 解决的,参考 Mixin At 的 ordinal 参数的思路。我就重载了 MethodVisitor#visitJumpInsn 使其替换了第 2 和第 3 个 if_acmpne 指令(需要替换的这两个 ==)。
youyihj 发表于 2023-1-10 14:36
我 Mixin 就看你的教程学的,ASM 你教程没写,催更
后来我就用 ASM Core API 解决的,参考 Mixin ...
我觉得这样的做法不可取,万一这个类被其他mod改了,需要替换的这两个 ==不再是第2、第3个if_acmpne就出问题了,还是根据上下文关系进行判断会比较靠谱
gooding300 发表于 2023-1-10 17:20
我觉得这样的做法不可取,万一这个类被其他mod改了,需要替换的这两个 ==不再是第2、第3个if_acmpne就出 ...
合理,如果是上下文处理的话。给自定义的 MethodVisitor 加一个 flag 字段,visitMethodInsn 方法中如果方法是 getID 方法,就把这个字段设为 true,然后 visitJumpInsn 检查这个字段为 true 后再进行操作。