More ASM, rewrite RNG

This commit is contained in:
JFronny 2021-10-25 18:58:41 +02:00
parent fd269ce9c8
commit e4a1d83b9b
No known key found for this signature in database
GPG Key ID: BEC5ACBBD4EE17E5
10 changed files with 89 additions and 93 deletions

View File

@ -5,24 +5,36 @@ 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.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
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 mathHelper = PatchUtil.getRemappedInternal("net/minecraft/class_3532");
private static final String mathHelperSin = mapMathHelper("method_15374", "(F)F");
private static final String mathHelperCos = mapMathHelper("method_15362", "(F)F");
private static final String mathHelperSqrt = mapMathHelper("method_15355", "(F)F");
private static final String mathHelperFloor = mapMathHelper("method_15375", "(F)F");
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 mapMathHelper(String method, String descriptor) {
return AsmTransformer.MAPPING_RESOLVER.mapMethodName(AsmTransformer.INTERMEDIARY, mathHelper.replace('/', '.'), method, descriptor);
private static String mth(String method, String descriptor) {
return AsmTransformer.MAPPING_RESOLVER.mapMethodName(AsmTransformer.INTERMEDIARY, mathHelperIntermediary, method, descriptor);
}
@Override
@ -32,46 +44,45 @@ public class BytecodeTransformer implements AsmConfig, Patch {
@Override
public Set<Patch> getPatches() {
return Cfg.rewriteMath ? Set.of(this) : Set.of();
return Set.of(this);
}
@Override
public void apply(ClassNode klazz) {
if (klazz.name.equals(mathUtil)) return;
for (MethodNode method : klazz.methods) {
for (AbstractInsnNode insn : method.instructions.toArray()) {
if (insn.getOpcode() == Opcodes.INVOKESTATIC) {
MethodInsnNode mIns = (MethodInsnNode) insn;
if (insn.getOpcode() == Opcodes.INVOKESTATIC || insn.getOpcode() == Opcodes.INVOKEVIRTUAL) {
String insNew = null;
if (Cfg.corruptTrigonometry) {
if (mIns.owner.equals(math)) {
if (mIns.name.equals("sin")) insNew = "sin";
else if (mIns.name.equals("cos")) insNew = "cos";
}
else if (mIns.owner.equals(mathHelper)) {
if (mIns.name.equals(mathHelperSin)) insNew = "sin";
else if (mIns.name.equals(mathHelperCos)) insNew = "cos";
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;
}
}
if (Cfg.corruptGenericMath) {
if (mIns.owner.equals(math)) {
if (mIns.name.equals("sqrt")) insNew = "sqrt";
}
else if (mIns.owner.equals(mathHelper)) {
if (mIns.name.equals(mathHelperSqrt)) insNew = "sqrt";
}
}
if (Cfg.corruptGenericMath2) {
if (mIns.owner.equals(math)) {
if (mIns.name.equals("floor")) insNew = "floor";
}
else if (mIns.owner.equals(mathHelper)) {
if (mIns.name.equals(mathHelperFloor)) insNew = "floor";
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) {
method.instructions.insertBefore(mIns, new MethodInsnNode(Opcodes.INVOKESTATIC, mathUtil, insNew, mIns.desc));
method.instructions.remove(mIns);
if (mIns.getOpcode() == Opcodes.INVOKEVIRTUAL)
method.instructions.insertBefore(mIns, new InsnNode(Opcodes.POP));
mIns.setOpcode(Opcodes.INVOKESTATIC);
mIns.owner = mathUtil;
mIns.name = insNew;
}
}
}

View File

@ -7,13 +7,13 @@ public class Cfg implements JfConfig {
@Entry
public static Boolean corruptGenericMath = true;
@Entry
public static Boolean corruptGenericMath2 = false;
@Entry
public static Boolean corruptTrigonometry = true;
@Entry
public static Boolean corruptGenericMath2 = false;
public static Boolean corruptTrigonometry2 = true;
@Entry
public static Boolean corruptPerlinNoise = true;
@Entry
public static Boolean corruptSimplexNoise = true;
@Entry
public static Boolean rewriteMath = false;
}

View File

@ -4,6 +4,7 @@ import net.minecraft.util.math.MathHelper;
import java.util.Random;
@SuppressWarnings("unused")
public class MathUtil {
private static final float[] SIN_TABLE_FAST = new float[4096];
private static final float radToIndex = 651.8986469044033F;
@ -46,19 +47,19 @@ public class MathUtil {
return boxedInvert(MathHelper.floor(value), MathHelper.ceil(value), value);
}
public static float sin(float value) {
public static float sinM(float value) {
return SIN_TABLE_FAST[(int) (value * radToIndex) & 4095];
}
public static double sin(double value) {
return sin((float) value);
return sinM((float) value);
}
public static float cos(float value) {
return sin(value);
public static float cosM(float value) {
return sinM(value);
}
public static double cos(double value) {
return cos((float) value);
return sinM((float) value);
}
public static float sqrt(float value) {
public static float sqrtM(float value) {
return (float)Math.pow(value, 0.6);
}
public static double sqrt(double value) {
@ -70,4 +71,24 @@ public class MathUtil {
public static double floor(double value) {
return floor((float) value);
}
public static int nextInt() {
return 2;
}
public static int nextInt(int bound) {
return Math.min(2, bound);
}
public static long nextLong() {
return 2;
}
public static boolean nextBoolean() {
return false;
}
public static float nextFloat() {
return Float.MIN_NORMAL;
}
public static double random() {
return Double.MIN_NORMAL;
}
}

View File

@ -25,8 +25,6 @@ public class MixinPlugin implements IMixinConfigPlugin {
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
if (Objects.equals(mixinClassName, MathHelperMixin.class.getName()))
return Cfg.corruptGenericMath;
else if (Objects.equals(mixinClassName, MathHelperTrigonometryMixin.class.getName()))
return Cfg.corruptTrigonometry;
else if (Objects.equals(mixinClassName, MathHelperMixin2.class.getName()))
return Cfg.corruptGenericMath2;
else if (Objects.equals(mixinClassName, MixinPerlinNoiseSampler.class.getName()))

View File

@ -19,11 +19,6 @@ public abstract class MathHelperMixin {
@Shadow public static int floor(double value) { return 0; }
@Shadow public static double nextDouble(Random random, double min, double max) { return 0; }
@Overwrite
public static float sqrt(float f) {
return MathUtil.sqrt(f);
}
@Overwrite
public static int fastFloor(double d) {
return (int)(d / 32) * 32;

View File

@ -2,7 +2,6 @@ package io.gitlab.jfronny.quickmeth.mixin;
import net.minecraft.util.math.MathHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@ -14,11 +13,6 @@ public class MathHelperMixin2 {
ci.setReturnValue(ci.getReturnValue() * 1.2f);
}
@Overwrite
public static int floor(float f) {
return (int)(f / 4) * 4;
}
@Inject(method = "ceil(F)I", at = @At("TAIL"), cancellable = true)
private static void shortenCeilF(CallbackInfoReturnable<Integer> ci) {
ci.setReturnValue(ci.getReturnValue() / 2 + 1);

View File

@ -1,25 +0,0 @@
package io.gitlab.jfronny.quickmeth.mixin;
import io.gitlab.jfronny.quickmeth.MathUtil;
import net.minecraft.util.math.MathHelper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(MathHelper.class)
public class MathHelperTrigonometryMixin {
@Inject(method = "sin(F)F", at = @At("TAIL"), cancellable = true)
private static void invertSin(CallbackInfoReturnable<Float> ci) {
ci.setReturnValue(MathUtil.boxedInvert(ci.getReturnValue()));
}
@Overwrite
public static float sin(float f) {
return MathUtil.sin(f);
}
@Overwrite
public static float cos(float f) { return MathUtil.cos(f); }
}

View File

@ -2,14 +2,14 @@
"quickmeth.jfconfig.title": "QuickMäth",
"quickmeth.jfconfig.corruptGenericMath": "Corrupt generic math",
"quickmeth.jfconfig.corruptGenericMath.tooltip": "Corrupts methods in MathHelper. This will impact many things but most notably movement",
"quickmeth.jfconfig.corruptTrigonometry": "Corrupt Trigonometry",
"quickmeth.jfconfig.corruptTrigonometry.tooltip": "Corrupts trigonometry methods in MathHelper. Effects vary",
"quickmeth.jfconfig.corruptGenericMath2": "Corrupt more generic math",
"quickmeth.jfconfig.corruptGenericMath2.tooltip": "Corrupts more methods in MathHelper. These WILL break a lot of things so they are separate",
"quickmeth.jfconfig.corruptTrigonometry": "Corrupt Trigonometry",
"quickmeth.jfconfig.corruptTrigonometry.tooltip": "Corrupts trigonometry methods. Effects vary",
"quickmeth.jfconfig.corruptTrigonometry2": "Corrupt more Trigonometry",
"quickmeth.jfconfig.corruptTrigonometry2.tooltip": "Corrupts all trigonometry methods. This WILL break a lot of things",
"quickmeth.jfconfig.corruptPerlinNoise": "Corrupt perlin noise",
"quickmeth.jfconfig.corruptPerlinNoise.tooltip": "Corrupts methods in OctavePerlinNoiseSampler and PerlinNoiseSampler. This will mostly impact world generation",
"quickmeth.jfconfig.corruptSimplexNoise": "Corrupt simplex noise",
"quickmeth.jfconfig.corruptSimplexNoise.tooltip": "Corrupts methods in SimplexNoiseSampler. I am actually not sure what this breaks",
"quickmeth.jfconfig.rewriteMath": "Rewrite methods using ASM to not use java.lang.Math",
"quickmeth.jfconfig.rewriteMath.tooltip": "This allows QuickMäth to have an effect on more things"
"quickmeth.jfconfig.corruptSimplexNoise.tooltip": "Corrupts methods in SimplexNoiseSampler. I am actually not sure what this breaks"
}

View File

@ -3,7 +3,7 @@
"id": "quickmeth",
"version": "${version}",
"name": "Quickmeth",
"description": "Math sucks so why not break it?",
"description": "Replaces math methods with incorrect alternatives",
"authors": [
"JFronny"
],
@ -37,6 +37,9 @@
"custom": {
"lithium:options": {
"mixin.gen.perlin_noise": false
},
"libjf": {
"asm.export": false
}
}
}

View File

@ -7,7 +7,6 @@
"mixins": [
"MathHelperMixin",
"MathHelperMixin2",
"MathHelperTrigonometryMixin",
"MixinPerlinNoiseSampler",
"MixinSimplexNoiseSampler"
],