| /* Copyright 2015-2020 Rivoreo |
| |
| This Source Code Form is subject to the terms of the Mozilla Public |
| License, v. 2.0. If a copy of the MPL was not distributed with this |
| file, You can obtain one at https://mozilla.org/MPL/2.0/. |
| */ |
| |
| package rivoreo.minecraft.cauldronfix; |
| |
| import net.minecraft.launchwrapper.IClassTransformer; |
| import org.objectweb.asm.ClassReader; |
| import org.objectweb.asm.ClassWriter; |
| import org.objectweb.asm.tree.ClassNode; |
| import org.objectweb.asm.tree.MethodNode; |
| import org.objectweb.asm.tree.AbstractInsnNode; |
| import org.objectweb.asm.tree.IntInsnNode; |
| import org.objectweb.asm.tree.LdcInsnNode; |
| import org.objectweb.asm.tree.MethodInsnNode; |
| import org.objectweb.asm.Opcodes; |
| import java.util.List; |
| |
| public class CauldronFixTransformer implements IClassTransformer { |
| private static byte[] transform_minecraftserver(byte[] class_code) { |
| ClassReader reader = new ClassReader(class_code); |
| ClassNode class_node = new ClassNode(); |
| reader.accept(class_node, ClassReader.SKIP_DEBUG); |
| for(MethodNode method : (List<MethodNode>)class_node.methods) { |
| if(method.desc.matches("\\(Ljava/lang/String;Ljava/lang/String;JL(afy|ahm|net/minecraft/world/WorldType);Ljava/lang/String;\\)V") && (method.name.equals("a") || method.name.equals("func_71247_a")) && method.access == Opcodes.ACC_PROTECTED) { |
| AbstractInsnNode[] insn_nodes = method.instructions.toArray(); |
| for(int i = 0; i < insn_nodes.length - 75; i++) { |
| if(insn_nodes[i].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.IFNONNULL) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.INVOKESTATIC) continue; |
| if(insn_nodes[i + 4].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 5].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 6].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| MethodInsnNode method_insn = (MethodInsnNode)insn_nodes[i + 6]; |
| if(!method_insn.owner.equals("java/lang/Object")) continue; |
| if(!method_insn.name.equals("getClass")) continue; |
| if(insn_nodes[i + 7].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 8].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 9].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 10].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 11].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 12].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 13].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 14].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 15].getOpcode() != Opcodes.NEW) continue; |
| if(insn_nodes[i + 16].getOpcode() != Opcodes.DUP) continue; |
| if(insn_nodes[i + 17].getOpcode() != Opcodes.INVOKESPECIAL) continue; |
| if(insn_nodes[i + 18].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 19].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 20].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 21].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 22].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 23].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 24].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 25].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 26].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 27].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 28].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 29].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 30].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 31].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 32].getOpcode() != Opcodes.INVOKESTATIC) continue; |
| if(insn_nodes[i + 33].getOpcode() != Opcodes.INVOKESTATIC) continue; |
| if(insn_nodes[i + 34].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 35].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 36].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 37].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 38].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 39].getOpcode() != Opcodes.IFNONNULL) continue; |
| if(insn_nodes[i + 40].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 41].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 42].getType() != AbstractInsnNode.LABEL) continue; |
| if(insn_nodes[i + 43].getType() != AbstractInsnNode.FRAME) continue; |
| if(insn_nodes[i + 44].getOpcode() != Opcodes.GOTO) continue; |
| if(insn_nodes[i + 45].getType() != AbstractInsnNode.LABEL) continue; |
| if(insn_nodes[i + 46].getType() != AbstractInsnNode.FRAME) continue; |
| if(insn_nodes[i + 47].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 48].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 49].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 50].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 51].getOpcode() != Opcodes.NEW) continue; |
| if(insn_nodes[i + 52].getOpcode() != Opcodes.DUP) continue; |
| if(insn_nodes[i + 53].getOpcode() != Opcodes.INVOKESPECIAL) continue; |
| if(insn_nodes[i + 54].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 55].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 56].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 57].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 58].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 59].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 60].getOpcode() != Opcodes.NEW) continue; |
| if(insn_nodes[i + 61].getOpcode() != Opcodes.DUP) continue; |
| if(insn_nodes[i + 62].getOpcode() != Opcodes.INVOKESPECIAL) continue; |
| if(insn_nodes[i + 63].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 64].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 65].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 66].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 67].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 68].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 69].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 70].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 71].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 72].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 73].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 74].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 75].getOpcode() != Opcodes.ASTORE) continue; |
| method.instructions.remove(insn_nodes[i]); |
| method.instructions.remove(insn_nodes[i + 1]); |
| method_insn.owner = "net/minecraft/world/WorldProvider"; |
| method_insn.name = "func_80007_l"; |
| method_insn.desc = "()Ljava/lang/String;"; |
| method.instructions.remove(insn_nodes[i + 7]); |
| // Remove [i + 10] ~ [i + 34] |
| for(int j = i + 10; j < i + 35; j++) { |
| method.instructions.remove(insn_nodes[j]); |
| } |
| // Remove [i + 44] ~ [i + 59] |
| for(int j = i + 44; j < i + 60; j++) { |
| method.instructions.remove(insn_nodes[j]); |
| } |
| break; |
| } |
| } |
| } |
| ClassWriter writer = new ClassWriter(0); |
| class_node.accept(writer); |
| return writer.toByteArray(); |
| } |
| |
| private static byte[] transform_minecraftforge_dimensionmanager(byte[] class_code) { |
| ClassReader reader = new ClassReader(class_code); |
| ClassNode class_node = new ClassNode(); |
| reader.accept(class_node, ClassReader.SKIP_DEBUG); |
| for(MethodNode method : (List<MethodNode>)class_node.methods) { |
| if(method.desc.equals("(I)V") && method.name.equals("initDimension") && method.access == (Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC)) { |
| AbstractInsnNode[] insn_nodes = method.instructions.toArray(); |
| for(int i = 0; i < insn_nodes.length - 87; i++) { |
| int first_opcode = insn_nodes[i].getOpcode(); |
| if(insn_nodes[i].getOpcode() == Opcodes.ILOAD) { |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.ICONST_M1) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.IF_ICMPLT) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 4].getOpcode() != Opcodes.ICONST_1) continue; |
| if(insn_nodes[i + 5].getOpcode() != Opcodes.IF_ICMPGT) continue; |
| if(insn_nodes[i + 6].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 7].getOpcode() != Opcodes.ICONST_M1) continue; |
| if(insn_nodes[i + 8].getOpcode() != Opcodes.IF_ICMPNE) continue; |
| if(insn_nodes[i + 9].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 10].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 11].getOpcode() != Opcodes.IFEQ) continue; |
| if(insn_nodes[i + 12].getType() != AbstractInsnNode.LABEL) continue; |
| if(insn_nodes[i + 13].getType() != AbstractInsnNode.FRAME) continue; |
| if(insn_nodes[i + 14].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 15].getOpcode() != Opcodes.ICONST_1) continue; |
| if(insn_nodes[i + 16].getOpcode() != Opcodes.IF_ICMPNE) continue; |
| if(insn_nodes[i + 17].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 18].getOpcode() != Opcodes.GETFIELD) continue; |
| if(insn_nodes[i + 19].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 20].getOpcode() != Opcodes.IFNE) continue; |
| if(insn_nodes[i + 21].getType() != AbstractInsnNode.LABEL) continue; |
| if(insn_nodes[i + 22].getType() != AbstractInsnNode.FRAME) continue; |
| if(insn_nodes[i + 23].getOpcode() != Opcodes.RETURN) continue; |
| if(insn_nodes[i + 24].getType() != AbstractInsnNode.LABEL) continue; |
| if(insn_nodes[i + 25].getType() != AbstractInsnNode.FRAME) continue; |
| if(insn_nodes[i + 26].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 27].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 28].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 29].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 30].getOpcode() != Opcodes.NEW) continue; |
| if(insn_nodes[i + 31].getOpcode() != Opcodes.DUP) continue; |
| if(insn_nodes[i + 32].getOpcode() != Opcodes.INVOKESPECIAL) continue; |
| if(insn_nodes[i + 33].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 34].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 35].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 36].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 37].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 38].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 39].getOpcode() != Opcodes.GOTO) continue; |
| if(insn_nodes[i + 40].getType() != AbstractInsnNode.LABEL) continue; |
| if(insn_nodes[i + 41].getType() != AbstractInsnNode.FRAME) continue; |
| if(insn_nodes[i + 42].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 43].getOpcode() != Opcodes.INVOKESTATIC) continue; |
| if(insn_nodes[i + 44].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 45].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 46].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| MethodInsnNode method_insn = (MethodInsnNode)insn_nodes[i + 46]; |
| if(!method_insn.owner.equals("java/lang/Object")) continue; |
| if(!method_insn.name.equals("getClass")) continue; |
| if(insn_nodes[i + 47].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 48].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 49].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 50].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 51].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 52].getOpcode() != Opcodes.LDC) continue; |
| LdcInsnNode ldc_insn = (LdcInsnNode)insn_nodes[i + 52]; |
| if(!(ldc_insn.cst instanceof String)) continue; |
| if(!((String)ldc_insn.cst).isEmpty()) continue; |
| if(insn_nodes[i + 53].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 54].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 55].getOpcode() != Opcodes.NEW) continue; |
| if(insn_nodes[i + 56].getOpcode() != Opcodes.DUP) continue; |
| if(insn_nodes[i + 57].getOpcode() != Opcodes.INVOKESPECIAL) continue; |
| if(insn_nodes[i + 58].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 59].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 60].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 61].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 62].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 63].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 64].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 65].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 66].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 67].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 68].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 69].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 70].getOpcode() != Opcodes.INVOKESTATIC) continue; |
| if(insn_nodes[i + 71].getOpcode() != Opcodes.INVOKESTATIC) continue; |
| if(insn_nodes[i + 72].getOpcode() != Opcodes.IFNONNULL) continue; |
| if(insn_nodes[i + 73].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 74].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 75].getOpcode() != Opcodes.INVOKESTATIC) continue; |
| if(insn_nodes[i + 76].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 77].getOpcode() != Opcodes.INVOKESTATIC) continue; |
| if(insn_nodes[i + 78].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 79].getType() != AbstractInsnNode.LABEL) continue; |
| if(insn_nodes[i + 80].getType() != AbstractInsnNode.FRAME) continue; |
| if(insn_nodes[i + 81].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 82].getOpcode() != Opcodes.INVOKEVIRTUAL) continue; |
| if(insn_nodes[i + 83].getOpcode() != Opcodes.ASTORE) continue; |
| if(insn_nodes[i + 84].getOpcode() != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 85].getOpcode() != Opcodes.IFNONNULL) continue; |
| if(insn_nodes[i + 86].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 87].getOpcode() != Opcodes.ASTORE) continue; |
| // Remove [i + 0] ~ [i + 5] |
| for(int j = i; j < i + 6; j++) { |
| method.instructions.remove(insn_nodes[j]); |
| } |
| // Remove [i + 26] ~ [i + 41] |
| for(int j = i + 26; j < i + 42; j++) { |
| method.instructions.remove(insn_nodes[j]); |
| } |
| method_insn.owner = "net/minecraft/world/WorldProvider"; |
| method_insn.name = "func_80007_l"; |
| method_insn.desc = "()Ljava/lang/String;"; |
| method.instructions.remove(insn_nodes[i + 47]); |
| /* |
| ldc_insn.cst = Character.valueOf('_'); |
| ldc_insn = (LdcInsnNode)insn_nodes[i + 51]; |
| ldc_insn.cst = Character.valueOf(' '); |
| */ |
| // Remove [i + 49] ~ [i + 52] |
| for(int j = i + 49; j < i + 53; j++) { |
| method.instructions.remove(insn_nodes[j]); |
| } |
| method_insn = (MethodInsnNode)insn_nodes[i + 53]; |
| method_insn.desc = "(CC)Ljava/lang/String;"; |
| method.instructions.insertBefore(method_insn, new IntInsnNode(Opcodes.BIPUSH, 0x20)); |
| method.instructions.insertBefore(method_insn, new IntInsnNode(Opcodes.BIPUSH, 0x5f)); |
| // Remove [i + 64] ~ [i + 68] |
| for(int j = i + 64; j < i + 69; j++) { |
| method.instructions.remove(insn_nodes[j]); |
| } |
| // Remove [i + 69] ~ [i + 80] |
| for(int j = i + 69; j < i + 81; j++) { |
| method.instructions.remove(insn_nodes[j]); |
| } |
| i += 87; |
| } else if(first_opcode == Opcodes.LDC) { |
| LdcInsnNode ldc_insn = (LdcInsnNode)insn_nodes[i]; |
| if(!(ldc_insn.cst instanceof String)) continue; |
| if(!((String)ldc_insn.cst).equals("world-environment-settings.")) continue; |
| ldc_insn.cst = "world-settings."; |
| } |
| } |
| } |
| } |
| ClassWriter writer = new ClassWriter(0); |
| class_node.accept(writer); |
| return writer.toByteArray(); |
| } |
| |
| public byte[] transform(String original_name, String runtime_name, byte[] class_code) { |
| if(runtime_name.equals("net.minecraft.server.MinecraftServer")) return transform_minecraftserver(class_code); |
| if(runtime_name.equals("net.minecraftforge.common.DimensionManager")) return transform_minecraftforge_dimensionmanager(class_code); |
| return class_code; |
| } |
| } |