QuickMath/src/main/java/io/gitlab/jfronny/quickmeth/BytecodeTransformer.java
2022-04-03 20:32:40 +02:00

92 lines
3.8 KiB
Java

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<String, String> 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<String, Boolean> 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<String> skipClasses() {
return null;
}
@Override
public Set<Patch> 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;
}
}
}
}
}
}