More ASM, rewrite RNG
This commit is contained in:
parent
fd269ce9c8
commit
e4a1d83b9b
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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()))
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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); }
|
||||
}
|
@ -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"
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
"mixins": [
|
||||
"MathHelperMixin",
|
||||
"MathHelperMixin2",
|
||||
"MathHelperTrigonometryMixin",
|
||||
"MixinPerlinNoiseSampler",
|
||||
"MixinSimplexNoiseSampler"
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user