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.Patch;
import io.gitlab.jfronny.libjf.unsafe.asm.patch.PatchUtil; import io.gitlab.jfronny.libjf.unsafe.asm.patch.PatchUtil;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import java.util.Map;
import java.util.Set; import java.util.Set;
public class BytecodeTransformer implements AsmConfig, Patch { public class BytecodeTransformer implements AsmConfig, Patch {
private static final String math = "java/lang/Math"; 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 mathUtil = "io/gitlab/jfronny/quickmeth/MathUtil";
private static final String mathHelper = PatchUtil.getRemappedInternal("net/minecraft/class_3532"); private static final String mathHelperIntermediary = "net.minecraft.class_3532";
private static final String mathHelperSin = mapMathHelper("method_15374", "(F)F"); private static final String mathHelper = PatchUtil.getRemappedInternal(mathHelperIntermediary);
private static final String mathHelperCos = mapMathHelper("method_15362", "(F)F"); private static final Map<String, String> mth = Map.of(
private static final String mathHelperSqrt = mapMathHelper("method_15355", "(F)F"); mth("method_15374", "(F)F"), "sinM",
private static final String mathHelperFloor = mapMathHelper("method_15375", "(F)F"); 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) { private static String mth(String method, String descriptor) {
return AsmTransformer.MAPPING_RESOLVER.mapMethodName(AsmTransformer.INTERMEDIARY, mathHelper.replace('/', '.'), method, descriptor); return AsmTransformer.MAPPING_RESOLVER.mapMethodName(AsmTransformer.INTERMEDIARY, mathHelperIntermediary, method, descriptor);
} }
@Override @Override
@ -32,46 +44,45 @@ public class BytecodeTransformer implements AsmConfig, Patch {
@Override @Override
public Set<Patch> getPatches() { public Set<Patch> getPatches() {
return Cfg.rewriteMath ? Set.of(this) : Set.of(); return Set.of(this);
} }
@Override @Override
public void apply(ClassNode klazz) { public void apply(ClassNode klazz) {
if (klazz.name.equals(mathUtil)) return;
for (MethodNode method : klazz.methods) { for (MethodNode method : klazz.methods) {
for (AbstractInsnNode insn : method.instructions.toArray()) { for (AbstractInsnNode insn : method.instructions.toArray()) {
if (insn.getOpcode() == Opcodes.INVOKESTATIC) { if (insn.getOpcode() == Opcodes.INVOKESTATIC || insn.getOpcode() == Opcodes.INVOKEVIRTUAL) {
MethodInsnNode mIns = (MethodInsnNode) insn;
String insNew = null; String insNew = null;
if (Cfg.corruptTrigonometry) { MethodInsnNode mIns = (MethodInsnNode) insn;
if (mIns.owner.equals(math)) { if (mIns.owner.equals(math)) {
if (mIns.name.equals("sin")) insNew = "sin"; if (stat.containsKey(mIns.name) && stat.get(mIns.name))
else if (mIns.name.equals("cos")) insNew = "cos"; insNew = mIns.name;
} }
else if (mIns.owner.equals(mathHelper)) { else if (mIns.owner.equals(mathHelper)) {
if (mIns.name.equals(mathHelperSin)) insNew = "sin"; if (mth.containsKey(mIns.name)) {
else if (mIns.name.equals(mathHelperCos)) insNew = "cos"; insNew = mth.get(mIns.name);
if (!stat.get(insNew))
insNew = null;
} }
} }
if (Cfg.corruptGenericMath) { else if (mIns.owner.equals(random)) {
if (mIns.owner.equals(math)) { if (Cfg.corruptGenericMath2 && !klazz.name.equals(mathUtil)) {
if (mIns.name.equals("sqrt")) insNew = "sqrt"; insNew = switch (mIns.name) {
} //case "nextInt" -> "nextInt";
else if (mIns.owner.equals(mathHelper)) { case "nextLong" -> "nextLong";
if (mIns.name.equals(mathHelperSqrt)) insNew = "sqrt"; case "nextBoolean" -> "nextBoolean";
} //case "nextFloat" -> "nextFloat";
} case "nextDouble", "nextGaussian" -> "random";
if (Cfg.corruptGenericMath2) { default -> null;
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";
} }
} }
if (insNew != null) { if (insNew != null) {
method.instructions.insertBefore(mIns, new MethodInsnNode(Opcodes.INVOKESTATIC, mathUtil, insNew, mIns.desc)); if (mIns.getOpcode() == Opcodes.INVOKEVIRTUAL)
method.instructions.remove(mIns); 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 @Entry
public static Boolean corruptGenericMath = true; public static Boolean corruptGenericMath = true;
@Entry @Entry
public static Boolean corruptGenericMath2 = false;
@Entry
public static Boolean corruptTrigonometry = true; public static Boolean corruptTrigonometry = true;
@Entry @Entry
public static Boolean corruptGenericMath2 = false; public static Boolean corruptTrigonometry2 = true;
@Entry @Entry
public static Boolean corruptPerlinNoise = true; public static Boolean corruptPerlinNoise = true;
@Entry @Entry
public static Boolean corruptSimplexNoise = true; 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; import java.util.Random;
@SuppressWarnings("unused")
public class MathUtil { public class MathUtil {
private static final float[] SIN_TABLE_FAST = new float[4096]; private static final float[] SIN_TABLE_FAST = new float[4096];
private static final float radToIndex = 651.8986469044033F; private static final float radToIndex = 651.8986469044033F;
@ -46,19 +47,19 @@ public class MathUtil {
return boxedInvert(MathHelper.floor(value), MathHelper.ceil(value), value); 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]; return SIN_TABLE_FAST[(int) (value * radToIndex) & 4095];
} }
public static double sin(double value) { public static double sin(double value) {
return sin((float) value); return sinM((float) value);
} }
public static float cos(float value) { public static float cosM(float value) {
return sin(value); return sinM(value);
} }
public static double cos(double 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); return (float)Math.pow(value, 0.6);
} }
public static double sqrt(double value) { public static double sqrt(double value) {
@ -70,4 +71,24 @@ public class MathUtil {
public static double floor(double value) { public static double floor(double value) {
return floor((float) 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) { public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
if (Objects.equals(mixinClassName, MathHelperMixin.class.getName())) if (Objects.equals(mixinClassName, MathHelperMixin.class.getName()))
return Cfg.corruptGenericMath; return Cfg.corruptGenericMath;
else if (Objects.equals(mixinClassName, MathHelperTrigonometryMixin.class.getName()))
return Cfg.corruptTrigonometry;
else if (Objects.equals(mixinClassName, MathHelperMixin2.class.getName())) else if (Objects.equals(mixinClassName, MathHelperMixin2.class.getName()))
return Cfg.corruptGenericMath2; return Cfg.corruptGenericMath2;
else if (Objects.equals(mixinClassName, MixinPerlinNoiseSampler.class.getName())) 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 int floor(double value) { return 0; }
@Shadow public static double nextDouble(Random random, double min, double max) { 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 @Overwrite
public static int fastFloor(double d) { public static int fastFloor(double d) {
return (int)(d / 32) * 32; return (int)(d / 32) * 32;

View File

@ -2,7 +2,6 @@ package io.gitlab.jfronny.quickmeth.mixin;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@ -14,11 +13,6 @@ public class MathHelperMixin2 {
ci.setReturnValue(ci.getReturnValue() * 1.2f); 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) @Inject(method = "ceil(F)I", at = @At("TAIL"), cancellable = true)
private static void shortenCeilF(CallbackInfoReturnable<Integer> ci) { private static void shortenCeilF(CallbackInfoReturnable<Integer> ci) {
ci.setReturnValue(ci.getReturnValue() / 2 + 1); 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.title": "QuickMäth",
"quickmeth.jfconfig.corruptGenericMath": "Corrupt generic math", "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.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": "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.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": "Corrupt perlin noise",
"quickmeth.jfconfig.corruptPerlinNoise.tooltip": "Corrupts methods in OctavePerlinNoiseSampler and PerlinNoiseSampler. This will mostly impact world generation", "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": "Corrupt simplex noise",
"quickmeth.jfconfig.corruptSimplexNoise.tooltip": "Corrupts methods in SimplexNoiseSampler. I am actually not sure what this breaks", "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"
} }

View File

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

View File

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