package io.gitlab.jfronny.quickmeth; import io.gitlab.jfronny.libjf.unsafe.asm.AsmConfig; import io.gitlab.jfronny.libjf.unsafe.asm.AsmTransformer; import io.gitlab.jfronny.libjf.unsafe.asm.patch.Patch; import io.gitlab.jfronny.libjf.unsafe.asm.patch.PatchUtil; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.*; import java.util.Map; import java.util.Set; public class BytecodeTransformer implements AsmConfig, Patch { private static final String math = "java/lang/Math"; private static final String random = "java/util/Random"; private static final String mathUtil = "io/gitlab/jfronny/quickmeth/MathUtil"; private static final String mathHelperIntermediary = "net.minecraft.class_3532"; private static final String mathHelper = PatchUtil.getRemappedInternal(mathHelperIntermediary); private static final Map mth = Map.of( mth("method_15374", "(F)F"), "sinM", mth("method_15362", "(F)F"), "cosM", mth("method_15355", "(F)F"), "sqrtM", mth("method_15375", "(D)I"), "floor" ); private static final Map stat = Map.of( "sin", Cfg.corruptTrigonometry2, "cos", Cfg.corruptTrigonometry2, "sinM", Cfg.corruptTrigonometry, "cosM", Cfg.corruptTrigonometry, //"sqrt", Cfg.corruptGenericMath, "sqrtM", Cfg.corruptGenericMath, "floor", Cfg.corruptGenericMath2, "random", Cfg.corruptGenericMath2 ); private static String mth(String method, String descriptor) { return AsmTransformer.MAPPING_RESOLVER.mapMethodName(AsmTransformer.INTERMEDIARY, mathHelperIntermediary, method, descriptor); } @Override public Set skipClasses() { return null; } @Override public Set getPatches() { return Set.of(this); } @Override public void apply(ClassNode klazz) { for (MethodNode method : klazz.methods) { for (AbstractInsnNode insn : method.instructions.toArray()) { if (insn.getOpcode() == Opcodes.INVOKESTATIC || insn.getOpcode() == Opcodes.INVOKEVIRTUAL) { String insNew = null; MethodInsnNode mIns = (MethodInsnNode) insn; if (mIns.owner.equals(math)) { if (stat.containsKey(mIns.name) && stat.get(mIns.name)) insNew = mIns.name; } else if (mIns.owner.equals(mathHelper)) { if (mth.containsKey(mIns.name)) { insNew = mth.get(mIns.name); if (!stat.get(insNew)) insNew = null; } } else if (mIns.owner.equals(random)) { if (Cfg.corruptGenericMath2 && !klazz.name.equals(mathUtil)) { insNew = switch (mIns.name) { //case "nextInt" -> "nextInt"; case "nextLong" -> "nextLong"; case "nextBoolean" -> "nextBoolean"; //case "nextFloat" -> "nextFloat"; case "nextDouble", "nextGaussian" -> "random"; default -> null; }; } } if (insNew != null) { if (mIns.getOpcode() == Opcodes.INVOKEVIRTUAL) method.instructions.insertBefore(mIns, new InsnNode(Opcodes.POP)); mIns.setOpcode(Opcodes.INVOKESTATIC); mIns.owner = mathUtil; mIns.name = insNew; } } } } } }