blob: b9a3900d66eb04d290707ab7956fcb923c2782f8 [file] [log] [blame] [raw]
/* 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;
}
}