9
0
mirror of https://github.com/BX-Team/DivineMC.git synced 2025-12-28 11:19:19 +00:00

sort classes

This commit is contained in:
NONPLAYT
2025-07-17 18:44:04 +03:00
parent 14bec37171
commit be5a07876c
82 changed files with 370 additions and 391 deletions

View File

@@ -0,0 +1,13 @@
package com.ishland.c2me.opts.dfc.common;
import net.minecraft.world.level.levelgen.NoiseRouterData;
public interface IDensityFunctionsCaveScaler {
static double invokeScaleCaves(double value) {
return NoiseRouterData.QuantizedSpaghettiRarity.getSphaghettiRarity2D(value);
}
static double invokeScaleTunnels(double value) {
return NoiseRouterData.QuantizedSpaghettiRarity.getSpaghettiRarity3D(value);
}
}

View File

@@ -0,0 +1,22 @@
package com.ishland.c2me.opts.dfc.common.ast;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import org.objectweb.asm.commons.InstructionAdapter;
public interface AstNode {
double evalSingle(int var1, int var2, int var3, EvalType var4);
void evalMulti(double[] var1, int[] var2, int[] var3, int[] var4, EvalType var5);
AstNode[] getChildren();
AstNode transform(AstTransformer var1);
void doBytecodeGenSingle(BytecodeGen.Context var1, InstructionAdapter var2, BytecodeGen.Context.LocalVarConsumer var3);
void doBytecodeGenMulti(BytecodeGen.Context var1, InstructionAdapter var2, BytecodeGen.Context.LocalVarConsumer var3);
boolean relaxedEquals(AstNode var1);
int relaxedHashCode();
}

View File

@@ -0,0 +1,5 @@
package com.ishland.c2me.opts.dfc.common.ast;
public interface AstTransformer {
AstNode transform(AstNode var1);
}

View File

@@ -0,0 +1,25 @@
package com.ishland.c2me.opts.dfc.common.ast;
import com.ishland.c2me.opts.dfc.common.vif.EachApplierVanillaInterface;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.NoiseChunk;
public enum EvalType {
NORMAL,
INTERPOLATION;
private EvalType() {
}
public static EvalType from(DensityFunction.FunctionContext pos) {
return pos instanceof NoiseChunk ? INTERPOLATION : NORMAL;
}
public static EvalType from(DensityFunction.ContextProvider applier) {
if (applier instanceof EachApplierVanillaInterface vif) {
return vif.getType();
} else {
return applier instanceof NoiseChunk ? INTERPOLATION : NORMAL;
}
}
}

View File

@@ -0,0 +1,106 @@
package com.ishland.c2me.opts.dfc.common.ast;
import com.ishland.c2me.opts.dfc.common.ast.binary.AddNode;
import com.ishland.c2me.opts.dfc.common.ast.binary.MaxNode;
import com.ishland.c2me.opts.dfc.common.ast.binary.MaxShortNode;
import com.ishland.c2me.opts.dfc.common.ast.binary.MinNode;
import com.ishland.c2me.opts.dfc.common.ast.binary.MinShortNode;
import com.ishland.c2me.opts.dfc.common.ast.binary.MulNode;
import com.ishland.c2me.opts.dfc.common.ast.misc.CacheLikeNode;
import com.ishland.c2me.opts.dfc.common.ast.misc.ConstantNode;
import com.ishland.c2me.opts.dfc.common.ast.misc.DelegateNode;
import com.ishland.c2me.opts.dfc.common.ast.misc.RangeChoiceNode;
import com.ishland.c2me.opts.dfc.common.ast.misc.YClampedGradientNode;
import com.ishland.c2me.opts.dfc.common.ast.noise.DFTNoiseNode;
import com.ishland.c2me.opts.dfc.common.ast.noise.DFTShiftANode;
import com.ishland.c2me.opts.dfc.common.ast.noise.DFTShiftBNode;
import com.ishland.c2me.opts.dfc.common.ast.noise.DFTShiftNode;
import com.ishland.c2me.opts.dfc.common.ast.noise.DFTWeirdScaledSamplerNode;
import com.ishland.c2me.opts.dfc.common.ast.noise.ShiftedNoiseNode;
import com.ishland.c2me.opts.dfc.common.ast.spline.SplineAstNode;
import com.ishland.c2me.opts.dfc.common.ast.unary.AbsNode;
import com.ishland.c2me.opts.dfc.common.ast.unary.CubeNode;
import com.ishland.c2me.opts.dfc.common.ast.unary.NegMulNode;
import com.ishland.c2me.opts.dfc.common.ast.unary.SquareNode;
import com.ishland.c2me.opts.dfc.common.ast.unary.SqueezeNode;
import com.ishland.c2me.opts.dfc.common.ducks.IEqualityOverriding;
import com.ishland.c2me.opts.dfc.common.ducks.IFastCacheLike;
import com.ishland.c2me.opts.dfc.common.vif.AstVanillaInterface;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.DensityFunctions;
import net.minecraft.world.level.levelgen.NoiseChunk;
import org.jetbrains.annotations.NotNull;
public class McToAst {
public McToAst() {
}
public static AstNode toAst(DensityFunction df) {
Objects.requireNonNull(df);
return switch (df) {
case AstVanillaInterface f -> f.getAstNode();
case NoiseChunk.BlendAlpha f -> new ConstantNode(1.0);
case NoiseChunk.BlendOffset f -> new ConstantNode(0.0);
case DensityFunctions.BlendAlpha f -> new ConstantNode(1.0);
case DensityFunctions.BlendOffset f -> new ConstantNode(0.0);
case DensityFunctions.TwoArgumentSimpleFunction f -> switch (f.type()) {
case ADD -> new AddNode(toAst(f.argument1()), toAst(f.argument2()));
case MUL -> new MulNode(toAst(f.argument1()), toAst(f.argument2()));
case MIN -> {
double rightMin = f.argument2().minValue();
if (f.argument1().minValue() < rightMin) {
yield new MinShortNode(toAst(f.argument1()), toAst(f.argument2()), rightMin);
} else {
yield new MinNode(toAst(f.argument1()), toAst(f.argument2()));
}
}
case MAX -> {
double rightMax = f.argument2().maxValue();
if (f.argument1().maxValue() > rightMax) {
yield new MaxShortNode(toAst(f.argument1()), toAst(f.argument2()), rightMax);
} else {
yield new MaxNode(toAst(f.argument1()), toAst(f.argument2()));
}
}
};
case DensityFunctions.BlendDensity f -> toAst(f.input());
case DensityFunctions.Clamp f -> new MaxNode(new ConstantNode(f.minValue()), new MinNode(new ConstantNode(f.maxValue()), toAst(f.input())));
case DensityFunctions.Constant f -> new ConstantNode(f.value());
case DensityFunctions.HolderHolder f -> toAst(f.function().value());
case DensityFunctions.Mapped f -> switch (f.type()) {
case ABS -> new AbsNode(toAst(f.input()));
case SQUARE -> new SquareNode(toAst(f.input()));
case CUBE -> new CubeNode(toAst(f.input()));
case HALF_NEGATIVE -> new NegMulNode(toAst(f.input()), 0.5);
case QUARTER_NEGATIVE -> new NegMulNode(toAst(f.input()), 0.25);
case SQUEEZE -> new SqueezeNode(toAst(f.input()));
};
case DensityFunctions.RangeChoice f -> new RangeChoiceNode(toAst(f.input()), f.minInclusive(), f.maxExclusive(), toAst(f.whenInRange()), toAst(f.whenOutOfRange()));
case DensityFunctions.Marker f -> {
DensityFunctions.Marker wrapping = new DensityFunctions.Marker(f.type(), new AstVanillaInterface(toAst(f.wrapped()), null));
((IEqualityOverriding) (Object) wrapping).c2me$overrideEquality(wrapping);
yield new DelegateNode(wrapping);
}
case IFastCacheLike f -> new CacheLikeNode(f, toAst(f.c2me$getDelegate()));
case DensityFunctions.ShiftedNoise f -> new ShiftedNoiseNode(toAst(f.shiftX()), toAst(f.shiftY()), toAst(f.shiftZ()), f.xzScale(), f.yScale(), f.noise());
case DensityFunctions.Noise f -> new DFTNoiseNode(f.noise(), f.xzScale(), f.yScale());
case DensityFunctions.Shift f -> new DFTShiftNode(f.offsetNoise());
case DensityFunctions.ShiftA f -> new DFTShiftANode(f.offsetNoise());
case DensityFunctions.ShiftB f -> new DFTShiftBNode(f.offsetNoise());
case DensityFunctions.YClampedGradient f -> new YClampedGradientNode(f.fromY(), f.toY(), f.fromValue(), f.toValue());
case DensityFunctions.WeirdScaledSampler f -> new DFTWeirdScaledSamplerNode(toAst(f.input()), f.noise(), f.rarityValueMapper());
case DensityFunctions.Spline f -> new SplineAstNode(f.spline());
default -> {
// delegateStatistics.computeIfAbsent(df.getClass(), unused -> new LongAdder()).increment();;
yield new DelegateNode(df);
}
};
}
public static @NotNull DensityFunction wrapVanilla(DensityFunction densityFunction) {
return new AstVanillaInterface(toAst(densityFunction), densityFunction);
}
}

View File

@@ -0,0 +1,106 @@
package com.ishland.c2me.opts.dfc.common.ast.binary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen.Context;
import com.ishland.c2me.opts.dfc.common.util.ArrayCache;
import java.util.Objects;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public abstract class AbstractBinaryNode implements AstNode {
protected final AstNode left;
protected final AstNode right;
public AbstractBinaryNode(AstNode left, AstNode right) {
this.left = (AstNode)Objects.requireNonNull(left);
this.right = (AstNode)Objects.requireNonNull(right);
}
public AstNode[] getChildren() {
return new AstNode[]{this.left, this.right};
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
AbstractBinaryNode that = (AbstractBinaryNode)o;
return Objects.equals(this.left, that.left) && Objects.equals(this.right, that.right);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.left.hashCode();
result = 31 * result + this.right.hashCode();
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
AbstractBinaryNode that = (AbstractBinaryNode)o;
return this.left.relaxedEquals(that.left) && this.right.relaxedEquals(that.right);
} else {
return false;
}
}
public int relaxedHashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.left.relaxedHashCode();
result = 31 * result + this.right.relaxedHashCode();
return result;
}
protected abstract AstNode newInstance(AstNode var1, AstNode var2);
public AstNode transform(AstTransformer transformer) {
AstNode left = this.left.transform(transformer);
AstNode right = this.right.transform(transformer);
return left == this.left && right == this.right ? transformer.transform(this) : transformer.transform(this.newInstance(left, right));
}
public void doBytecodeGenSingle(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String leftMethod = context.newSingleMethod(this.left);
String rightMethod = context.newSingleMethod(this.right);
context.callDelegateSingle(m, leftMethod);
context.callDelegateSingle(m, rightMethod);
}
public void doBytecodeGenMulti(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String leftMethod = context.newMultiMethod(this.left);
String rightMethod = context.newMultiMethod(this.right);
int res1 = localVarConsumer.createLocalVariable("res1", Type.getDescriptor(double[].class));
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.arraylength();
m.iconst(0);
m.invokevirtual(Type.getInternalName(ArrayCache.class), "getDoubleArray", Type.getMethodDescriptor(Type.getType(double[].class), new Type[]{Type.INT_TYPE, Type.BOOLEAN_TYPE}), false);
m.store(res1, InstructionAdapter.OBJECT_TYPE);
context.callDelegateMulti(m, leftMethod);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(res1, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, rightMethod, Context.MULTI_DESC, false);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
this.bytecodeGenMultiBody(m, idx, res1);
});
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.load(res1, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(Type.getInternalName(ArrayCache.class), "recycle", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(double[].class)}), false);
m.areturn(Type.VOID_TYPE);
}
protected abstract void bytecodeGenMultiBody(InstructionAdapter var1, int var2, int var3);
}

View File

@@ -0,0 +1,50 @@
package com.ishland.c2me.opts.dfc.common.ast.binary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class AddNode extends AbstractBinaryNode {
public AddNode(AstNode left, AstNode right) {
super(left, right);
}
protected AstNode newInstance(AstNode left, AstNode right) {
return new AddNode(left, right);
}
public double evalSingle(int x, int y, int z, EvalType type) {
return this.left.evalSingle(x, y, z, type) + this.right.evalSingle(x, y, z, type);
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
double[] res1 = new double[res.length];
this.left.evalMulti(res, x, y, z, type);
this.right.evalMulti(res1, x, y, z, type);
for(int i = 0; i < res1.length; ++i) {
res[i] += res1[i];
}
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenSingle(context, m, localVarConsumer);
m.add(Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
protected void bytecodeGenMultiBody(InstructionAdapter m, int idx, int res1) {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.dup2();
m.aload(Type.DOUBLE_TYPE);
m.load(res1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.add(Type.DOUBLE_TYPE);
m.astore(Type.DOUBLE_TYPE);
}
}

View File

@@ -0,0 +1,50 @@
package com.ishland.c2me.opts.dfc.common.ast.binary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class MaxNode extends AbstractBinaryNode {
public MaxNode(AstNode left, AstNode right) {
super(left, right);
}
protected AstNode newInstance(AstNode left, AstNode right) {
return new MaxNode(left, right);
}
public double evalSingle(int x, int y, int z, EvalType type) {
return Math.max(this.left.evalSingle(x, y, z, type), this.right.evalSingle(x, y, z, type));
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
double[] res1 = new double[res.length];
this.left.evalMulti(res, x, y, z, type);
this.right.evalMulti(res1, x, y, z, type);
for(int i = 0; i < res1.length; ++i) {
res[i] = Math.max(res[i], res1[i]);
}
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenSingle(context, m, localVarConsumer);
m.invokestatic(Type.getInternalName(Math.class), "max", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.areturn(Type.DOUBLE_TYPE);
}
protected void bytecodeGenMultiBody(InstructionAdapter m, int idx, int res1) {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.dup2();
m.aload(Type.DOUBLE_TYPE);
m.load(res1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.invokestatic(Type.getInternalName(Math.class), "max", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.astore(Type.DOUBLE_TYPE);
}
}

View File

@@ -0,0 +1,92 @@
package com.ishland.c2me.opts.dfc.common.ast.binary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen.Context;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class MaxShortNode extends AbstractBinaryNode {
private final double rightMax;
public MaxShortNode(AstNode left, AstNode right, double rightMax) {
super(left, right);
this.rightMax = rightMax;
}
protected AstNode newInstance(AstNode left, AstNode right) {
return new MaxShortNode(left, right, this.rightMax);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double evaled = this.left.evalSingle(x, y, z, type);
return evaled >= this.rightMax ? evaled : Math.max(evaled, this.right.evalSingle(x, y, z, type));
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.left.evalMulti(res, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
res[i] = res[i] >= this.rightMax ? res[i] : Math.max(res[i], this.right.evalSingle(x[i], y[i], z[i], type));
}
}
public void doBytecodeGenSingle(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String leftMethod = context.newSingleMethod(this.left);
String rightMethod = context.newSingleMethod(this.right);
Label minLabel = new Label();
context.callDelegateSingle(m, leftMethod);
m.dup2();
m.dconst(this.rightMax);
m.cmpl(Type.DOUBLE_TYPE);
m.iflt(minLabel);
m.areturn(Type.DOUBLE_TYPE);
m.visitLabel(minLabel);
context.callDelegateSingle(m, rightMethod);
m.invokestatic(Type.getInternalName(Math.class), "max", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String leftMethod = context.newMultiMethod(this.left);
String rightMethodSingle = context.newSingleMethod(this.right);
context.callDelegateMulti(m, leftMethod);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
Label minLabel = new Label();
Label end = new Label();
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.dup2();
m.dconst(this.rightMax);
m.cmpl(Type.DOUBLE_TYPE);
m.iflt(minLabel);
m.goTo(end);
m.visitLabel(minLabel);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, rightMethodSingle, Context.SINGLE_DESC, false);
m.invokestatic(Type.getInternalName(Math.class), "max", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.visitLabel(end);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
protected void bytecodeGenMultiBody(InstructionAdapter m, int idx, int res1) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,50 @@
package com.ishland.c2me.opts.dfc.common.ast.binary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class MinNode extends AbstractBinaryNode {
public MinNode(AstNode left, AstNode right) {
super(left, right);
}
protected AstNode newInstance(AstNode left, AstNode right) {
return new MinNode(left, right);
}
public double evalSingle(int x, int y, int z, EvalType type) {
return Math.min(this.left.evalSingle(x, y, z, type), this.right.evalSingle(x, y, z, type));
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
double[] res1 = new double[res.length];
this.left.evalMulti(res, x, y, z, type);
this.right.evalMulti(res1, x, y, z, type);
for(int i = 0; i < res1.length; ++i) {
res[i] = Math.min(res[i], res1[i]);
}
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenSingle(context, m, localVarConsumer);
m.invokestatic(Type.getInternalName(Math.class), "min", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.areturn(Type.DOUBLE_TYPE);
}
protected void bytecodeGenMultiBody(InstructionAdapter m, int idx, int res1) {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.dup2();
m.aload(Type.DOUBLE_TYPE);
m.load(res1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.invokestatic(Type.getInternalName(Math.class), "min", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.astore(Type.DOUBLE_TYPE);
}
}

View File

@@ -0,0 +1,92 @@
package com.ishland.c2me.opts.dfc.common.ast.binary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen.Context;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class MinShortNode extends AbstractBinaryNode {
private final double rightMin;
public MinShortNode(AstNode left, AstNode right, double rightMin) {
super(left, right);
this.rightMin = rightMin;
}
protected AstNode newInstance(AstNode left, AstNode right) {
return new MinShortNode(left, right, this.rightMin);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double evaled = this.left.evalSingle(x, y, z, type);
return evaled <= this.rightMin ? evaled : Math.min(evaled, this.right.evalSingle(x, y, z, type));
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.left.evalMulti(res, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
res[i] = res[i] <= this.rightMin ? res[i] : Math.min(res[i], this.right.evalSingle(x[i], y[i], z[i], type));
}
}
public void doBytecodeGenSingle(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String leftMethod = context.newSingleMethod(this.left);
String rightMethod = context.newSingleMethod(this.right);
Label minLabel = new Label();
context.callDelegateSingle(m, leftMethod);
m.dup2();
m.dconst(this.rightMin);
m.cmpg(Type.DOUBLE_TYPE);
m.ifgt(minLabel);
m.areturn(Type.DOUBLE_TYPE);
m.visitLabel(minLabel);
context.callDelegateSingle(m, rightMethod);
m.invokestatic(Type.getInternalName(Math.class), "min", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String leftMethod = context.newMultiMethod(this.left);
String rightMethodSingle = context.newSingleMethod(this.right);
context.callDelegateMulti(m, leftMethod);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
Label minLabel = new Label();
Label end = new Label();
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.dup2();
m.dconst(this.rightMin);
m.cmpg(Type.DOUBLE_TYPE);
m.ifgt(minLabel);
m.goTo(end);
m.visitLabel(minLabel);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, rightMethodSingle, Context.SINGLE_DESC, false);
m.invokestatic(Type.getInternalName(Math.class), "min", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.visitLabel(end);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
protected void bytecodeGenMultiBody(InstructionAdapter m, int idx, int res1) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,92 @@
package com.ishland.c2me.opts.dfc.common.ast.binary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen.Context;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class MulNode extends AbstractBinaryNode {
public MulNode(AstNode left, AstNode right) {
super(left, right);
}
protected AstNode newInstance(AstNode left, AstNode right) {
return new MulNode(left, right);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double evaled = this.left.evalSingle(x, y, z, type);
return evaled == 0.0 ? 0.0 : evaled * this.right.evalSingle(x, y, z, type);
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.left.evalMulti(res, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
res[i] = res[i] == 0.0 ? 0.0 : res[i] * this.right.evalSingle(x[i], y[i], z[i], type);
}
}
public void doBytecodeGenSingle(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String leftMethod = context.newSingleMethod(this.left);
String rightMethod = context.newSingleMethod(this.right);
Label notZero = new Label();
context.callDelegateSingle(m, leftMethod);
m.dup2();
m.dconst(0.0);
m.cmpl(Type.DOUBLE_TYPE);
m.ifne(notZero);
m.dconst(0.0);
m.areturn(Type.DOUBLE_TYPE);
m.visitLabel(notZero);
context.callDelegateSingle(m, rightMethod);
m.mul(Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String leftMethod = context.newMultiMethod(this.left);
String rightMethodSingle = context.newSingleMethod(this.right);
context.callDelegateMulti(m, leftMethod);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
Label minLabel = new Label();
Label end = new Label();
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.dup2();
m.dconst(0.0);
m.cmpl(Type.DOUBLE_TYPE);
m.ifne(minLabel);
m.pop2();
m.dconst(0.0);
m.goTo(end);
m.visitLabel(minLabel);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, rightMethodSingle, Context.SINGLE_DESC, false);
m.mul(Type.DOUBLE_TYPE);
m.visitLabel(end);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
protected void bytecodeGenMultiBody(InstructionAdapter m, int idx, int res1) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,23 @@
package com.ishland.c2me.opts.dfc.common.ast.dfvisitor;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.DensityFunctions;
import net.minecraft.world.level.levelgen.NoiseChunk;
import org.jetbrains.annotations.NotNull;
public class StripBlending implements DensityFunction.Visitor {
public static final StripBlending INSTANCE = new StripBlending();
private StripBlending() {
}
public @NotNull DensityFunction apply(@NotNull DensityFunction densityFunction) {
return switch (densityFunction) {
case NoiseChunk.BlendAlpha ignored -> DensityFunctions.constant(1.0);
case NoiseChunk.BlendOffset ignored -> DensityFunctions.constant(0.0);
case DensityFunctions.BlendAlpha ignored -> DensityFunctions.constant(1.0);
case DensityFunctions.BlendOffset ignored -> DensityFunctions.constant(0.0);
default -> densityFunction;
};
}
}

View File

@@ -0,0 +1,256 @@
package com.ishland.c2me.opts.dfc.common.ast.misc;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.ducks.IFastCacheLike;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen.Context;
import com.ishland.c2me.opts.dfc.common.gen.IMultiMethod;
import com.ishland.c2me.opts.dfc.common.gen.ISingleMethod;
import com.ishland.c2me.opts.dfc.common.gen.SubCompiledDensityFunction;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.DensityFunctions;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class CacheLikeNode implements AstNode {
private final IFastCacheLike cacheLike;
private final AstNode delegate;
public CacheLikeNode(IFastCacheLike cacheLike, AstNode delegate) {
this.cacheLike = cacheLike;
this.delegate = (AstNode)Objects.requireNonNull(delegate);
}
public double evalSingle(int x, int y, int z, EvalType type) {
if (this.cacheLike == null) {
return this.delegate.evalSingle(x, y, z, type);
} else {
double cached = this.cacheLike.c2me$getCached(x, y, z, type);
if (Double.doubleToRawLongBits(cached) != 9222769054270909007L) {
return cached;
} else {
double eval = this.delegate.evalSingle(x, y, z, type);
this.cacheLike.c2me$cache(x, y, z, type, eval);
return eval;
}
}
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
if (this.cacheLike == null) {
this.delegate.evalMulti(res, x, y, z, type);
} else {
boolean cached = this.cacheLike.c2me$getCached(res, x, y, z, type);
if (!cached) {
this.delegate.evalMulti(res, x, y, z, type);
this.cacheLike.c2me$cache(res, x, y, z, type);
}
}
}
public AstNode[] getChildren() {
return new AstNode[]{this.delegate};
}
public AstNode transform(AstTransformer transformer) {
AstNode delegate = this.delegate.transform(transformer);
return this.delegate == delegate ? transformer.transform(this) : transformer.transform(new CacheLikeNode(this.cacheLike, delegate));
}
public void doBytecodeGenSingle(@NotNull Context context, @NotNull InstructionAdapter m, Context.@NotNull LocalVarConsumer localVarConsumer) {
String delegateMethod = context.newSingleMethod(this.delegate);
String cacheLikeField = context.newField(IFastCacheLike.class, this.cacheLike);
this.genPostprocessingMethod(context, cacheLikeField);
int eval = localVarConsumer.createLocalVariable("eval", Type.DOUBLE_TYPE.getDescriptor());
Label cacheExists = new Label();
Label cacheMiss = new Label();
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, cacheLikeField, Type.getDescriptor(IFastCacheLike.class));
m.ifnonnull(cacheExists);
context.callDelegateSingle(m, delegateMethod);
m.areturn(Type.DOUBLE_TYPE);
m.visitLabel(cacheExists);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, cacheLikeField, Type.getDescriptor(IFastCacheLike.class));
m.load(1, Type.INT_TYPE);
m.load(2, Type.INT_TYPE);
m.load(3, Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.invokeinterface(Type.getInternalName(IFastCacheLike.class), "c2me$getCached", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.INT_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.getType(EvalType.class)}));
m.dup2();
m.invokestatic(Type.getInternalName(Double.class), "doubleToRawLongBits", Type.getMethodDescriptor(Type.LONG_TYPE, new Type[]{Type.DOUBLE_TYPE}), false);
m.lconst(9222769054270909007L);
m.lcmp();
m.ifeq(cacheMiss);
m.areturn(Type.DOUBLE_TYPE);
m.visitLabel(cacheMiss);
m.pop2();
context.callDelegateSingle(m, delegateMethod);
m.store(eval, Type.DOUBLE_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, cacheLikeField, Type.getDescriptor(IFastCacheLike.class));
m.load(1, Type.INT_TYPE);
m.load(2, Type.INT_TYPE);
m.load(3, Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(eval, Type.DOUBLE_TYPE);
m.invokeinterface(Type.getInternalName(IFastCacheLike.class), "c2me$cache", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.INT_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.getType(EvalType.class), Type.DOUBLE_TYPE}));
m.load(eval, Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(@NotNull Context context, @NotNull InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String delegateMethod = context.newMultiMethod(this.delegate);
String cacheLikeField = context.newField(IFastCacheLike.class, this.cacheLike);
this.genPostprocessingMethod(context, cacheLikeField);
Label cacheExists = new Label();
Label cacheMiss = new Label();
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, cacheLikeField, Type.getDescriptor(IFastCacheLike.class));
m.ifnonnull(cacheExists);
context.callDelegateMulti(m, delegateMethod);
m.areturn(Type.VOID_TYPE);
m.visitLabel(cacheExists);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, cacheLikeField, Type.getDescriptor(IFastCacheLike.class));
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.invokeinterface(Type.getInternalName(IFastCacheLike.class), "c2me$getCached", Type.getMethodDescriptor(Type.BOOLEAN_TYPE, new Type[]{Type.getType(double[].class), Type.getType(int[].class), Type.getType(int[].class), Type.getType(int[].class), Type.getType(EvalType.class)}));
m.ifeq(cacheMiss);
m.areturn(Type.VOID_TYPE);
m.visitLabel(cacheMiss);
context.callDelegateMulti(m, delegateMethod);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, cacheLikeField, Type.getDescriptor(IFastCacheLike.class));
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.invokeinterface(Type.getInternalName(IFastCacheLike.class), "c2me$cache", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(double[].class), Type.getType(int[].class), Type.getType(int[].class), Type.getType(int[].class), Type.getType(EvalType.class)}));
m.areturn(Type.VOID_TYPE);
}
private void genPostprocessingMethod(@NotNull Context context, String cacheLikeField) {
String methodName = String.format("postProcessing_%s", cacheLikeField);
String delegateSingle = context.newSingleMethod(this.delegate);
String delegateMulti = context.newMultiMethod(this.delegate);
context.genPostprocessingMethod(methodName, (m) -> {
Label cacheExists = new Label();
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, cacheLikeField, Type.getDescriptor(IFastCacheLike.class));
m.dup();
m.ifnonnull(cacheExists);
m.pop();
m.pop();
m.areturn(Type.VOID_TYPE);
m.visitLabel(cacheExists);
m.anew(Type.getType(SubCompiledDensityFunction.class));
m.dup();
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.invokedynamic("evalSingle", Type.getMethodDescriptor(Type.getType(ISingleMethod.class), new Type[]{Type.getType(context.classDesc)}), new Handle(6, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;", false), new Object[]{Type.getMethodType(Context.SINGLE_DESC), new Handle(5, context.className, delegateSingle, Context.SINGLE_DESC, false), Type.getMethodType(Context.SINGLE_DESC)});
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.invokedynamic("evalMulti", Type.getMethodDescriptor(Type.getType(IMultiMethod.class), new Type[]{Type.getType(context.classDesc)}), new Handle(6, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;", false), new Object[]{Type.getMethodType(Context.MULTI_DESC), new Handle(5, context.className, delegateMulti, Context.MULTI_DESC, false), Type.getMethodType(Context.MULTI_DESC)});
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, cacheLikeField, Type.getDescriptor(IFastCacheLike.class));
m.checkcast(Type.getType(DensityFunction.class));
m.invokespecial(Type.getInternalName(SubCompiledDensityFunction.class), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(ISingleMethod.class), Type.getType(IMultiMethod.class), Type.getType(DensityFunction.class)}), false);
m.checkcast(Type.getType(DensityFunction.class));
m.invokeinterface(Type.getInternalName(IFastCacheLike.class), "c2me$withDelegate", Type.getMethodDescriptor(Type.getType(DensityFunction.class), new Type[]{Type.getType(DensityFunction.class)}));
m.putfield(context.className, cacheLikeField, Type.getDescriptor(IFastCacheLike.class));
m.areturn(Type.VOID_TYPE);
});
}
public IFastCacheLike getCacheLike() {
return this.cacheLike;
}
public AstNode getDelegate() {
return this.delegate;
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
CacheLikeNode that = (CacheLikeNode)o;
return equals(this.cacheLike, that.cacheLike) && Objects.equals(this.delegate, that.delegate);
} else {
return false;
}
}
private static boolean equals(IFastCacheLike a, IFastCacheLike b) {
if (a instanceof DensityFunctions.Marker wrappingA) {
if (b instanceof DensityFunctions.Marker wrappingB) {
return wrappingA.type() == wrappingB.type();
}
}
return a.equals(b);
}
public int hashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + hashCode(this.cacheLike);
result = 31 * result + this.delegate.hashCode();
return result;
}
private static int hashCode(IFastCacheLike o) {
if (o instanceof DensityFunctions.Marker wrapping) {
return wrapping.type().hashCode();
} else {
return o.hashCode();
}
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
CacheLikeNode that = (CacheLikeNode)o;
return relaxedEquals(this.cacheLike, that.cacheLike) && this.delegate.relaxedEquals(that.delegate);
} else {
return false;
}
}
private static boolean relaxedEquals(IFastCacheLike a, IFastCacheLike b) {
if (a instanceof DensityFunctions.Marker wrappingA) {
if (b instanceof DensityFunctions.Marker wrappingB) {
return wrappingA.type() == wrappingB.type();
}
}
return a.getClass() == b.getClass();
}
public int relaxedHashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + relaxedHashCode(this.cacheLike);
result = 31 * result + this.delegate.relaxedHashCode();
return result;
}
private static int relaxedHashCode(IFastCacheLike o) {
if (o instanceof DensityFunctions.Marker wrapping) {
return wrapping.type().hashCode();
} else {
return o.getClass().hashCode();
}
}
}

View File

@@ -0,0 +1,72 @@
package com.ishland.c2me.opts.dfc.common.ast.misc;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import java.util.Arrays;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class ConstantNode implements AstNode {
private final double value;
public ConstantNode(double value) {
this.value = value;
}
public double evalSingle(int x, int y, int z, EvalType type) {
return this.value;
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
Arrays.fill(res, this.value);
}
public AstNode[] getChildren() {
return new AstNode[0];
}
public AstNode transform(AstTransformer transformer) {
return transformer.transform(this);
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
m.dconst(this.value);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.dconst(this.value);
m.invokestatic(Type.getInternalName(Arrays.class), "fill", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(double[].class), Type.DOUBLE_TYPE}), false);
m.areturn(Type.VOID_TYPE);
}
public double getValue() {
return this.value;
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
ConstantNode that = (ConstantNode)o;
return Double.compare(this.value, that.value) == 0;
} else {
return false;
}
}
public int hashCode() {
return Double.hashCode(this.value);
}
public boolean relaxedEquals(AstNode o) {
return this.equals(o);
}
public int relaxedHashCode() {
return this.hashCode();
}
}

View File

@@ -0,0 +1,140 @@
package com.ishland.c2me.opts.dfc.common.ast.misc;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import com.ishland.c2me.opts.dfc.common.util.ArrayCache;
import com.ishland.c2me.opts.dfc.common.vif.EachApplierVanillaInterface;
import com.ishland.c2me.opts.dfc.common.vif.NoisePosVanillaInterface;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class DelegateNode implements AstNode {
private final DensityFunction densityFunction;
public DelegateNode(DensityFunction densityFunction) {
this.densityFunction = Objects.requireNonNull(densityFunction);
}
public double evalSingle(int x, int y, int z, EvalType type) {
return this.densityFunction.compute(new NoisePosVanillaInterface(x, y, z, type));
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
if (res.length == 1) {
res[0] = this.evalSingle(x[0], y[0], z[0], type);
} else {
this.densityFunction.fillArray(res, new EachApplierVanillaInterface(x, y, z, type));
}
}
public AstNode[] getChildren() {
return new AstNode[0];
}
public AstNode transform(AstTransformer transformer) {
return transformer.transform(this);
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String newField = context.newField(DensityFunction.class, this.densityFunction);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, newField, Type.getDescriptor(DensityFunction.class));
m.anew(Type.getType(NoisePosVanillaInterface.class));
m.dup();
m.load(1, Type.INT_TYPE);
m.load(2, Type.INT_TYPE);
m.load(3, Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.invokespecial(Type.getInternalName(NoisePosVanillaInterface.class), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.getType(EvalType.class)), false);
m.invokeinterface(Type.getInternalName(DensityFunction.class), "compute", Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.getType(DensityFunction.FunctionContext.class)));
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String newField = context.newField(DensityFunction.class, this.densityFunction);
Label moreThanTwoLabel = new Label();
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.arraylength();
m.iconst(1);
m.ificmpgt(moreThanTwoLabel);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.iconst(0);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, newField, Type.getDescriptor(DensityFunction.class));
m.anew(Type.getType(NoisePosVanillaInterface.class));
m.dup();
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.iconst(0);
m.aload(Type.INT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.iconst(0);
m.aload(Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.iconst(0);
m.aload(Type.INT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.invokespecial(Type.getInternalName(NoisePosVanillaInterface.class), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.getType(EvalType.class)), false);
m.invokeinterface(Type.getInternalName(DensityFunction.class), "compute", Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.getType(DensityFunction.FunctionContext.class)));
m.astore(Type.DOUBLE_TYPE);
m.areturn(Type.VOID_TYPE);
m.visitLabel(moreThanTwoLabel);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, newField, Type.getDescriptor(DensityFunction.class));
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.anew(Type.getType(EachApplierVanillaInterface.class));
m.dup();
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.invokespecial(Type.getInternalName(EachApplierVanillaInterface.class), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(int[].class), Type.getType(int[].class), Type.getType(int[].class), Type.getType(EvalType.class), Type.getType(ArrayCache.class)), false);
m.invokeinterface(Type.getInternalName(DensityFunction.class), "fillArray", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(double[].class), Type.getType(DensityFunction.ContextProvider.class)));
m.areturn(Type.VOID_TYPE);
}
public DensityFunction getDelegate() {
return this.densityFunction;
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DelegateNode that = (DelegateNode)o;
return Objects.equals(this.densityFunction, that.densityFunction);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
result = 31 * result + Objects.hashCode(this.getClass());
result = 31 * result + Objects.hashCode(this.densityFunction);
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DelegateNode that = (DelegateNode)o;
return this.densityFunction.getClass() == that.densityFunction.getClass();
} else {
return false;
}
}
public int relaxedHashCode() {
int result = 1;
result = 31 * result + Objects.hashCode(this.getClass());
result = 31 * result + Objects.hashCode(this.densityFunction.getClass());
return result;
}
}

View File

@@ -0,0 +1,337 @@
package com.ishland.c2me.opts.dfc.common.ast.misc;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen.Context;
import java.util.Objects;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class RangeChoiceNode implements AstNode {
private final AstNode input;
private final double minInclusive;
private final double maxExclusive;
private final AstNode whenInRange;
private final AstNode whenOutOfRange;
public RangeChoiceNode(AstNode input, double minInclusive, double maxExclusive, AstNode whenInRange, AstNode whenOutOfRange) {
this.input = (AstNode)Objects.requireNonNull(input);
this.minInclusive = minInclusive;
this.maxExclusive = maxExclusive;
this.whenInRange = (AstNode)Objects.requireNonNull(whenInRange);
this.whenOutOfRange = (AstNode)Objects.requireNonNull(whenOutOfRange);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double v = this.input.evalSingle(x, y, z, type);
return v >= this.minInclusive && v < this.maxExclusive ? this.whenInRange.evalSingle(x, y, z, type) : this.whenOutOfRange.evalSingle(x, y, z, type);
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.input.evalMulti(res, x, y, z, type);
int numInRange = 0;
int numOutOfRange;
for(numOutOfRange = 0; numOutOfRange < x.length; ++numOutOfRange) {
double v = res[numOutOfRange];
if (v >= this.minInclusive && v < this.maxExclusive) {
++numInRange;
}
}
numOutOfRange = res.length - numInRange;
if (numInRange == 0) {
this.evalChildMulti(this.whenOutOfRange, res, x, y, z, type);
} else if (numInRange == res.length) {
this.evalChildMulti(this.whenInRange, res, x, y, z, type);
} else {
int idx1 = 0;
int[] i1 = new int[numInRange];
double[] res1 = new double[numInRange];
int[] x1 = new int[numInRange];
int[] y1 = new int[numInRange];
int[] z1 = new int[numInRange];
int idx2 = 0;
int[] i2 = new int[numOutOfRange];
double[] res2 = new double[numOutOfRange];
int[] x2 = new int[numOutOfRange];
int[] y2 = new int[numOutOfRange];
int[] z2 = new int[numOutOfRange];
int i;
for(i = 0; i < res.length; ++i) {
double v = res[i];
int index;
if (v >= this.minInclusive && v < this.maxExclusive) {
index = idx1++;
i1[index] = i;
x1[index] = x[i];
y1[index] = y[i];
z1[index] = z[i];
} else {
index = idx2++;
i2[index] = i;
x2[index] = x[i];
y2[index] = y[i];
z2[index] = z[i];
}
}
this.evalChildMulti(this.whenInRange, res1, x1, y1, z1, type);
this.evalChildMulti(this.whenOutOfRange, res2, x2, y2, z2, type);
for(i = 0; i < numInRange; ++i) {
res[i1[i]] = res1[i];
}
for(i = 0; i < numOutOfRange; ++i) {
res[i2[i]] = res2[i];
}
}
}
public static void evalMultiStatic(double[] res, int[] x, int[] y, int[] z, EvalType type, double minInclusive, double maxExclusive, BytecodeGen.EvalSingleInterface whenInRangeSingle, BytecodeGen.EvalSingleInterface whenOutOfRangeSingle, BytecodeGen.EvalMultiInterface inputMulti, BytecodeGen.EvalMultiInterface whenInRangeMulti, BytecodeGen.EvalMultiInterface whenOutOfRangeMulti) {
inputMulti.evalMulti(res, x, y, z, type);
int numInRange = 0;
int numOutOfRange;
for(numOutOfRange = 0; numOutOfRange < x.length; ++numOutOfRange) {
double v = res[numOutOfRange];
if (v >= minInclusive && v < maxExclusive) {
++numInRange;
}
}
numOutOfRange = res.length - numInRange;
if (numInRange == 0) {
evalChildMulti(whenOutOfRangeSingle, whenOutOfRangeMulti, res, x, y, z, type);
} else if (numInRange == res.length) {
evalChildMulti(whenInRangeSingle, whenInRangeMulti, res, x, y, z, type);
} else {
int idx1 = 0;
int[] i1 = new int[numInRange];
double[] res1 = new double[numInRange];
int[] x1 = new int[numInRange];
int[] y1 = new int[numInRange];
int[] z1 = new int[numInRange];
int idx2 = 0;
int[] i2 = new int[numOutOfRange];
double[] res2 = new double[numOutOfRange];
int[] x2 = new int[numOutOfRange];
int[] y2 = new int[numOutOfRange];
int[] z2 = new int[numOutOfRange];
int i;
for(i = 0; i < res.length; ++i) {
double v = res[i];
int index;
if (v >= minInclusive && v < maxExclusive) {
index = idx1++;
i1[index] = i;
x1[index] = x[i];
y1[index] = y[i];
z1[index] = z[i];
} else {
index = idx2++;
i2[index] = i;
x2[index] = x[i];
y2[index] = y[i];
z2[index] = z[i];
}
}
evalChildMulti(whenInRangeSingle, whenInRangeMulti, res1, x1, y1, z1, type);
evalChildMulti(whenOutOfRangeSingle, whenOutOfRangeMulti, res2, x2, y2, z2, type);
for(i = 0; i < numInRange; ++i) {
res[i1[i]] = res1[i];
}
for(i = 0; i < numOutOfRange; ++i) {
res[i2[i]] = res2[i];
}
}
}
private static void evalChildMulti(BytecodeGen.EvalSingleInterface single, BytecodeGen.EvalMultiInterface multi, double[] res, int[] x, int[] y, int[] z, EvalType type) {
if (res.length == 1) {
res[0] = single.evalSingle(x[0], y[0], z[0], type);
} else {
multi.evalMulti(res, x, y, z, type);
}
}
private void evalChildMulti(AstNode child, double[] res, int[] x, int[] y, int[] z, EvalType type) {
if (res.length == 1) {
res[0] = child.evalSingle(x[0], y[0], z[0], type);
} else {
child.evalMulti(res, x, y, z, type);
}
}
public AstNode[] getChildren() {
return new AstNode[]{this.input, this.whenInRange, this.whenOutOfRange};
}
public AstNode transform(AstTransformer transformer) {
AstNode input = this.input.transform(transformer);
AstNode whenInRange = this.whenInRange.transform(transformer);
AstNode whenOutOfRange = this.whenOutOfRange.transform(transformer);
return this.input == input && this.whenInRange == whenInRange && this.whenOutOfRange == whenOutOfRange ? transformer.transform(this) : transformer.transform(new RangeChoiceNode(input, this.minInclusive, this.maxExclusive, whenInRange, whenOutOfRange));
}
public void doBytecodeGenSingle(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String inputMethod = context.newSingleMethod(this.input);
String whenInRangeMethod = context.newSingleMethod(this.whenInRange);
String whenOutOfRangeMethod = context.newSingleMethod(this.whenOutOfRange);
int inputValue = localVarConsumer.createLocalVariable("inputValue", Type.DOUBLE_TYPE.getDescriptor());
context.callDelegateSingle(m, inputMethod);
m.store(inputValue, Type.DOUBLE_TYPE);
Label whenOutOfRangeLabel = new Label();
Label end = new Label();
m.load(inputValue, Type.DOUBLE_TYPE);
m.dconst(this.minInclusive);
m.cmpl(Type.DOUBLE_TYPE);
m.iflt(whenOutOfRangeLabel);
m.load(inputValue, Type.DOUBLE_TYPE);
m.dconst(this.maxExclusive);
m.cmpg(Type.DOUBLE_TYPE);
m.ifge(whenOutOfRangeLabel);
if (whenInRangeMethod.equals(inputMethod)) {
m.load(inputValue, Type.DOUBLE_TYPE);
} else {
context.callDelegateSingle(m, whenInRangeMethod);
}
m.goTo(end);
m.visitLabel(whenOutOfRangeLabel);
if (whenOutOfRangeMethod.equals(inputMethod)) {
m.load(inputValue, Type.DOUBLE_TYPE);
} else {
context.callDelegateSingle(m, whenOutOfRangeMethod);
}
m.visitLabel(end);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String inputSingle = context.newSingleMethod(this.input);
String whenInRangeSingle = context.newSingleMethod(this.whenInRange);
String whenOutOfRangeSingle = context.newSingleMethod(this.whenOutOfRange);
String inputMulti = context.newMultiMethod(this.input);
context.callDelegateMulti(m, inputMulti);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
Label whenOutOfRangeLabel = new Label();
Label end = new Label();
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.dconst(this.minInclusive);
m.cmpl(Type.DOUBLE_TYPE);
m.iflt(whenOutOfRangeLabel);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.dconst(this.maxExclusive);
m.cmpg(Type.DOUBLE_TYPE);
m.ifge(whenOutOfRangeLabel);
if (whenInRangeSingle.equals(inputSingle)) {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
} else {
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, whenInRangeSingle, Context.SINGLE_DESC, false);
}
m.goTo(end);
m.visitLabel(whenOutOfRangeLabel);
if (whenOutOfRangeSingle.equals(inputSingle)) {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
} else {
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, whenOutOfRangeSingle, Context.SINGLE_DESC, false);
}
m.visitLabel(end);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
RangeChoiceNode that = (RangeChoiceNode)o;
return Double.compare(this.minInclusive, that.minInclusive) == 0 && Double.compare(this.maxExclusive, that.maxExclusive) == 0 && Objects.equals(this.input, that.input) && Objects.equals(this.whenInRange, that.whenInRange) && Objects.equals(this.whenOutOfRange, that.whenOutOfRange);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.input.hashCode();
result = 31 * result + Double.hashCode(this.minInclusive);
result = 31 * result + Double.hashCode(this.maxExclusive);
result = 31 * result + this.whenInRange.hashCode();
result = 31 * result + this.whenOutOfRange.hashCode();
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
RangeChoiceNode that = (RangeChoiceNode)o;
return Double.compare(this.minInclusive, that.minInclusive) == 0 && Double.compare(this.maxExclusive, that.maxExclusive) == 0 && this.input.relaxedEquals(that.input) && this.whenInRange.relaxedEquals(that.whenInRange) && this.whenOutOfRange.relaxedEquals(that.whenOutOfRange);
} else {
return false;
}
}
public int relaxedHashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.input.relaxedHashCode();
result = 31 * result + Double.hashCode(this.minInclusive);
result = 31 * result + Double.hashCode(this.maxExclusive);
result = 31 * result + this.whenInRange.relaxedHashCode();
result = 31 * result + this.whenOutOfRange.relaxedHashCode();
return result;
}
}

View File

@@ -0,0 +1,82 @@
package com.ishland.c2me.opts.dfc.common.ast.misc;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import java.util.Objects;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class RootNode implements AstNode {
private final AstNode next;
public RootNode(AstNode next) {
this.next = (AstNode)Objects.requireNonNull(next);
}
public double evalSingle(int x, int y, int z, EvalType type) {
return this.next.evalSingle(x, y, z, type);
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.next.evalMulti(res, x, y, z, type);
}
public AstNode[] getChildren() {
return new AstNode[]{this.next};
}
public AstNode transform(AstTransformer transformer) {
AstNode next = this.next.transform(transformer);
return next == this.next ? transformer.transform(this) : transformer.transform(new RootNode(next));
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String nextMethod = context.newSingleMethod(this.next);
context.callDelegateSingle(m, nextMethod);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String nextMethod = context.newMultiMethod(this.next);
context.callDelegateMulti(m, nextMethod);
m.areturn(Type.VOID_TYPE);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
RootNode that = (RootNode)o;
return Objects.equals(this.next, that.next);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.next.hashCode();
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
RootNode that = (RootNode)o;
return this.next.relaxedEquals(that.next);
} else {
return false;
}
}
public int relaxedHashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.next.relaxedHashCode();
return result;
}
}

View File

@@ -0,0 +1,100 @@
package com.ishland.c2me.opts.dfc.common.ast.misc;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import net.minecraft.util.Mth;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class YClampedGradientNode implements AstNode {
private final double fromY;
private final double toY;
private final double fromValue;
private final double toValue;
public YClampedGradientNode(double fromY, double toY, double fromValue, double toValue) {
this.fromY = fromY;
this.toY = toY;
this.fromValue = fromValue;
this.toValue = toValue;
}
public double evalSingle(int x, int y, int z, EvalType type) {
return Mth.clampedMap((double)y, this.fromY, this.toY, this.fromValue, this.toValue);
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
for(int i = 0; i < res.length; ++i) {
res[i] = Mth.clampedMap((double)y[i], this.fromY, this.toY, this.fromValue, this.toValue);
}
}
public AstNode[] getChildren() {
return new AstNode[0];
}
public AstNode transform(AstTransformer transformer) {
return transformer.transform(this);
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
m.load(2, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.fromY);
m.dconst(this.toY);
m.dconst(this.fromValue);
m.dconst(this.toValue);
m.invokestatic(Type.getInternalName(Mth.class), "clampedMap", "(DDDDD)D", false);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
context.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.fromY);
m.dconst(this.toY);
m.dconst(this.fromValue);
m.dconst(this.toValue);
m.invokestatic(Type.getInternalName(Mth.class), "clampedMap", "(DDDDD)D", false);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
YClampedGradientNode that = (YClampedGradientNode)o;
return Double.compare(this.fromY, that.fromY) == 0 && Double.compare(this.toY, that.toY) == 0 && Double.compare(this.fromValue, that.fromValue) == 0 && Double.compare(this.toValue, that.toValue) == 0;
} else {
return false;
}
}
public int hashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + Double.hashCode(this.fromY);
result = 31 * result + Double.hashCode(this.toY);
result = 31 * result + Double.hashCode(this.fromValue);
result = 31 * result + Double.hashCode(this.toValue);
return result;
}
public boolean relaxedEquals(AstNode o) {
return this.equals(o);
}
public int relaxedHashCode() {
return this.hashCode();
}
}

View File

@@ -0,0 +1,131 @@
package com.ishland.c2me.opts.dfc.common.ast.noise;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class DFTNoiseNode implements AstNode {
private final DensityFunction.NoiseHolder noise;
private final double xzScale;
private final double yScale;
public DFTNoiseNode(DensityFunction.NoiseHolder noise, double xzScale, double yScale) {
this.noise = (DensityFunction.NoiseHolder)Objects.requireNonNull(noise);
this.xzScale = xzScale;
this.yScale = yScale;
}
public double evalSingle(int x, int y, int z, EvalType type) {
return this.noise.getValue((double)x * this.xzScale, (double)y * this.yScale, (double)z * this.xzScale);
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
for(int i = 0; i < res.length; ++i) {
res[i] = this.noise.getValue((double)x[i] * this.xzScale, (double)y[i] * this.yScale, (double)z[i] * this.xzScale);
}
}
public AstNode[] getChildren() {
return new AstNode[0];
}
public AstNode transform(AstTransformer transformer) {
return transformer.transform(this);
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.noise);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(1, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.xzScale);
m.mul(Type.DOUBLE_TYPE);
m.load(2, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.yScale);
m.mul(Type.DOUBLE_TYPE);
m.load(3, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.xzScale);
m.mul(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.noise);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.xzScale);
m.mul(Type.DOUBLE_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.yScale);
m.mul(Type.DOUBLE_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.xzScale);
m.mul(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DFTNoiseNode that = (DFTNoiseNode)o;
return Double.compare(this.xzScale, that.xzScale) == 0 && Double.compare(this.yScale, that.yScale) == 0 && Objects.equals(this.noise, that.noise);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.noise.hashCode();
result = 31 * result + Double.hashCode(this.xzScale);
result = 31 * result + Double.hashCode(this.yScale);
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DFTNoiseNode that = (DFTNoiseNode)o;
return Double.compare(this.xzScale, that.xzScale) == 0 && Double.compare(this.yScale, that.yScale) == 0;
} else {
return false;
}
}
public int relaxedHashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + Double.hashCode(this.xzScale);
result = 31 * result + Double.hashCode(this.yScale);
return result;
}
}

View File

@@ -0,0 +1,115 @@
package com.ishland.c2me.opts.dfc.common.ast.noise;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class DFTShiftANode implements AstNode {
private final DensityFunction.NoiseHolder offsetNoise;
public DFTShiftANode(DensityFunction.NoiseHolder offsetNoise) {
this.offsetNoise = (DensityFunction.NoiseHolder)Objects.requireNonNull(offsetNoise);
}
public double evalSingle(int x, int y, int z, EvalType type) {
return this.offsetNoise.getValue((double)x * 0.25, 0.0, (double)z * 0.25) * 4.0;
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
for(int i = 0; i < res.length; ++i) {
res[i] = this.offsetNoise.getValue((double)x[i] * 0.25, 0.0, (double)z[i] * 0.25) * 4.0;
}
}
public AstNode[] getChildren() {
return new AstNode[0];
}
public AstNode transform(AstTransformer transformer) {
return transformer.transform(this);
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.offsetNoise);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(1, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.dconst(0.0);
m.load(3, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.dconst(4.0);
m.mul(Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.offsetNoise);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.dconst(0.0);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.dconst(4.0);
m.mul(Type.DOUBLE_TYPE);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DFTShiftANode that = (DFTShiftANode)o;
return Objects.equals(this.offsetNoise, that.offsetNoise);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
Object o = this.getClass();
result = 31 * result + o.hashCode();
result = 31 * result + this.offsetNoise.hashCode();
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else {
return o != null && this.getClass() == o.getClass();
}
}
public int relaxedHashCode() {
return this.getClass().hashCode();
}
}

View File

@@ -0,0 +1,115 @@
package com.ishland.c2me.opts.dfc.common.ast.noise;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class DFTShiftBNode implements AstNode {
private final DensityFunction.NoiseHolder offsetNoise;
public DFTShiftBNode(DensityFunction.NoiseHolder offsetNoise) {
this.offsetNoise = (DensityFunction.NoiseHolder)Objects.requireNonNull(offsetNoise);
}
public double evalSingle(int x, int y, int z, EvalType type) {
return this.offsetNoise.getValue((double)z * 0.25, (double)x * 0.25, 0.0) * 4.0;
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
for(int i = 0; i < res.length; ++i) {
res[i] = this.offsetNoise.getValue((double)z[i] * 0.25, (double)x[i] * 0.25, 0.0) * 4.0;
}
}
public AstNode[] getChildren() {
return new AstNode[0];
}
public AstNode transform(AstTransformer transformer) {
return transformer.transform(this);
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.offsetNoise);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(3, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.load(1, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.dconst(0.0);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.dconst(4.0);
m.mul(Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.offsetNoise);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.dconst(0.0);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.dconst(4.0);
m.mul(Type.DOUBLE_TYPE);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DFTShiftBNode that = (DFTShiftBNode)o;
return Objects.equals(this.offsetNoise, that.offsetNoise);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
Object o = this.getClass();
result = 31 * result + o.hashCode();
result = 31 * result + this.offsetNoise.hashCode();
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else {
return o != null && this.getClass() == o.getClass();
}
}
public int relaxedHashCode() {
return this.getClass().hashCode();
}
}

View File

@@ -0,0 +1,123 @@
package com.ishland.c2me.opts.dfc.common.ast.noise;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class DFTShiftNode implements AstNode {
private final DensityFunction.NoiseHolder offsetNoise;
public DFTShiftNode(DensityFunction.NoiseHolder offsetNoise) {
this.offsetNoise = (DensityFunction.NoiseHolder)Objects.requireNonNull(offsetNoise);
}
public double evalSingle(int x, int y, int z, EvalType type) {
return this.offsetNoise.getValue((double)x * 0.25, (double)y * 0.25, (double)z * 0.25) * 4.0;
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
for(int i = 0; i < res.length; ++i) {
res[i] = this.offsetNoise.getValue((double)x[i] * 0.25, (double)y[i] * 0.25, (double)z[i] * 0.25) * 4.0;
}
}
public AstNode[] getChildren() {
return new AstNode[0];
}
public AstNode transform(AstTransformer transformer) {
return transformer.transform(this);
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.offsetNoise);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(1, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.load(2, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.load(3, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.dconst(4.0);
m.mul(Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.offsetNoise);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(0.25);
m.mul(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.dconst(4.0);
m.mul(Type.DOUBLE_TYPE);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DFTShiftNode that = (DFTShiftNode)o;
return Objects.equals(this.offsetNoise, that.offsetNoise);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
Object o = this.getClass();
result = 31 * result + o.hashCode();
result = 31 * result + this.offsetNoise.hashCode();
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else {
return o != null && this.getClass() == o.getClass();
}
}
public int relaxedHashCode() {
return this.getClass().hashCode();
}
}

View File

@@ -0,0 +1,169 @@
package com.ishland.c2me.opts.dfc.common.ast.noise;
import com.ishland.c2me.opts.dfc.common.IDensityFunctionsCaveScaler;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.DensityFunctions;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class DFTWeirdScaledSamplerNode implements AstNode {
private final AstNode input;
private final DensityFunction.NoiseHolder noise;
private final DensityFunctions.WeirdScaledSampler.RarityValueMapper mapper;
public DFTWeirdScaledSamplerNode(AstNode input, DensityFunction.NoiseHolder noise, DensityFunctions.WeirdScaledSampler.RarityValueMapper mapper) {
this.input = Objects.requireNonNull(input);
this.noise = Objects.requireNonNull(noise);
this.mapper = Objects.requireNonNull(mapper);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double v = this.input.evalSingle(x, y, z, type);
double d = (this.mapper.mapper).get(v);
return d * Math.abs(this.noise.getValue((double)x / d, (double)y / d, (double)z / d));
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.input.evalMulti(res, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
double d = (this.mapper.mapper).get(res[i]);
res[i] = d * Math.abs(this.noise.getValue((double)x[i] / d, (double)y[i] / d, (double)z[i] / d));
}
}
public AstNode[] getChildren() {
return new AstNode[]{this.input};
}
public AstNode transform(AstTransformer transformer) {
AstNode input = this.input.transform(transformer);
return input == this.input ? transformer.transform(this) : transformer.transform(new DFTWeirdScaledSamplerNode(input, this.noise, this.mapper));
}
public void doBytecodeGenSingle(BytecodeGen.@NotNull Context context, InstructionAdapter m, BytecodeGen.Context.@NotNull LocalVarConsumer localVarConsumer) {
String inputMethod = context.newSingleMethod(this.input);
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.noise);
int scale = localVarConsumer.createLocalVariable("scale", Type.DOUBLE_TYPE.getDescriptor());
context.callDelegateSingle(m, inputMethod);
switch (this.mapper) {
case TYPE1 -> m.invokestatic(Type.getInternalName(IDensityFunctionsCaveScaler.class), "invokeScaleTunnels", Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.DOUBLE_TYPE), true);
case TYPE2 -> m.invokestatic(Type.getInternalName(IDensityFunctionsCaveScaler.class), "invokeScaleCaves", Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.DOUBLE_TYPE), true);
default -> throw new UnsupportedOperationException(String.format("Unknown mapper %s", this.mapper));
}
m.store(scale, Type.DOUBLE_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(1, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.load(scale, Type.DOUBLE_TYPE);
m.div(Type.DOUBLE_TYPE);
m.load(2, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.load(scale, Type.DOUBLE_TYPE);
m.div(Type.DOUBLE_TYPE);
m.load(3, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.load(scale, Type.DOUBLE_TYPE);
m.div(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.invokestatic(Type.getInternalName(Math.class), "abs", "(D)D", false);
m.load(scale, Type.DOUBLE_TYPE);
m.mul(Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String inputMethod = context.newMultiMethod(this.input);
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.noise);
context.callDelegateMulti(m, inputMethod);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
int scale = localVarConsumer.createLocalVariable("scale", Type.DOUBLE_TYPE.getDescriptor());
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
switch (this.mapper) {
case TYPE1 -> m.invokestatic(Type.getInternalName(IDensityFunctionsCaveScaler.class), "invokeScaleTunnels", Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.DOUBLE_TYPE), true);
case TYPE2 -> m.invokestatic(Type.getInternalName(IDensityFunctionsCaveScaler.class), "invokeScaleCaves", Type.getMethodDescriptor(Type.DOUBLE_TYPE, Type.DOUBLE_TYPE), true);
default -> throw new UnsupportedOperationException(String.format("Unknown mapper %s", this.mapper));
}
m.store(scale, Type.DOUBLE_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.load(scale, Type.DOUBLE_TYPE);
m.div(Type.DOUBLE_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.load(scale, Type.DOUBLE_TYPE);
m.div(Type.DOUBLE_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.load(scale, Type.DOUBLE_TYPE);
m.div(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.invokestatic(Type.getInternalName(Math.class), "abs", "(D)D", false);
m.load(scale, Type.DOUBLE_TYPE);
m.mul(Type.DOUBLE_TYPE);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DFTWeirdScaledSamplerNode that = (DFTWeirdScaledSamplerNode)o;
return Objects.equals(this.input, that.input) && Objects.equals(this.noise, that.noise) && this.mapper == that.mapper;
} else {
return false;
}
}
public int hashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.input.hashCode();
result = 31 * result + this.noise.hashCode();
result = 31 * result + this.mapper.hashCode();
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
DFTWeirdScaledSamplerNode that = (DFTWeirdScaledSamplerNode)o;
return this.input.relaxedEquals(that.input) && this.mapper == that.mapper;
} else {
return false;
}
}
public int relaxedHashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.input.relaxedHashCode();
result = 31 * result + this.mapper.hashCode();
return result;
}
}

View File

@@ -0,0 +1,215 @@
package com.ishland.c2me.opts.dfc.common.ast.noise;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen.Context;
import com.ishland.c2me.opts.dfc.common.util.ArrayCache;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class ShiftedNoiseNode implements AstNode {
private final AstNode shiftX;
private final AstNode shiftY;
private final AstNode shiftZ;
private final double xzScale;
private final double yScale;
private final DensityFunction.NoiseHolder noise;
public ShiftedNoiseNode(AstNode shiftX, AstNode shiftY, AstNode shiftZ, double xzScale, double yScale, DensityFunction.NoiseHolder noise) {
this.shiftX = (AstNode)Objects.requireNonNull(shiftX);
this.shiftY = (AstNode)Objects.requireNonNull(shiftY);
this.shiftZ = (AstNode)Objects.requireNonNull(shiftZ);
this.xzScale = xzScale;
this.yScale = yScale;
this.noise = (DensityFunction.NoiseHolder)Objects.requireNonNull(noise);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double d = (double)x * this.xzScale + this.shiftX.evalSingle(x, y, z, type);
double e = (double)y * this.yScale + this.shiftY.evalSingle(x, y, z, type);
double f = (double)z * this.xzScale + this.shiftZ.evalSingle(x, y, z, type);
return this.noise.getValue(d, e, f);
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
double[] res1 = new double[res.length];
double[] res2 = new double[res.length];
this.shiftX.evalMulti(res, x, y, z, type);
this.shiftY.evalMulti(res1, x, y, z, type);
this.shiftZ.evalMulti(res2, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
res[i] = this.noise.getValue((double)x[i] * this.xzScale + res[i], (double)y[i] * this.yScale + res1[i], (double)z[i] * this.xzScale + res2[i]);
}
}
public AstNode[] getChildren() {
return new AstNode[]{this.shiftX, this.shiftY, this.shiftZ};
}
public AstNode transform(AstTransformer transformer) {
AstNode shiftX = this.shiftX.transform(transformer);
AstNode shiftY = this.shiftY.transform(transformer);
AstNode shiftZ = this.shiftZ.transform(transformer);
return shiftX == this.shiftX && shiftY == this.shiftY && shiftZ == this.shiftZ ? transformer.transform(this) : transformer.transform(new ShiftedNoiseNode(shiftX, shiftY, shiftZ, this.xzScale, this.yScale, this.noise));
}
public void doBytecodeGenSingle(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.noise);
String shiftXMethod = context.newSingleMethod(this.shiftX);
String shiftYMethod = context.newSingleMethod(this.shiftY);
String shiftZMethod = context.newSingleMethod(this.shiftZ);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(1, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.xzScale);
m.mul(Type.DOUBLE_TYPE);
context.callDelegateSingle(m, shiftXMethod);
m.add(Type.DOUBLE_TYPE);
m.load(2, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.yScale);
m.mul(Type.DOUBLE_TYPE);
context.callDelegateSingle(m, shiftYMethod);
m.add(Type.DOUBLE_TYPE);
m.load(3, Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.xzScale);
m.mul(Type.DOUBLE_TYPE);
context.callDelegateSingle(m, shiftZMethod);
m.add(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(Context context, InstructionAdapter m, Context.LocalVarConsumer localVarConsumer) {
String noiseField = context.newField(DensityFunction.NoiseHolder.class, this.noise);
String shiftXMethod = context.newMultiMethod(this.shiftX);
String shiftYMethod = context.newMultiMethod(this.shiftY);
String shiftZMethod = context.newMultiMethod(this.shiftZ);
int res1 = localVarConsumer.createLocalVariable("res1", Type.getDescriptor(double[].class));
int res2 = localVarConsumer.createLocalVariable("res2", Type.getDescriptor(double[].class));
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.arraylength();
m.iconst(0);
m.invokevirtual(Type.getInternalName(ArrayCache.class), "getDoubleArray", Type.getMethodDescriptor(Type.getType(double[].class), new Type[]{Type.INT_TYPE, Type.BOOLEAN_TYPE}), false);
m.store(res1, InstructionAdapter.OBJECT_TYPE);
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.arraylength();
m.iconst(0);
m.invokevirtual(Type.getInternalName(ArrayCache.class), "getDoubleArray", Type.getMethodDescriptor(Type.getType(double[].class), new Type[]{Type.INT_TYPE, Type.BOOLEAN_TYPE}), false);
m.store(res2, InstructionAdapter.OBJECT_TYPE);
context.callDelegateMulti(m, shiftXMethod);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(res1, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, shiftYMethod, Context.MULTI_DESC, false);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(res2, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, shiftZMethod, Context.MULTI_DESC, false);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, noiseField, Type.getDescriptor(DensityFunction.NoiseHolder.class));
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.xzScale);
m.mul(Type.DOUBLE_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.add(Type.DOUBLE_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.yScale);
m.mul(Type.DOUBLE_TYPE);
m.load(res1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.add(Type.DOUBLE_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
m.dconst(this.xzScale);
m.mul(Type.DOUBLE_TYPE);
m.load(res2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.DOUBLE_TYPE);
m.add(Type.DOUBLE_TYPE);
m.invokevirtual(Type.getInternalName(DensityFunction.NoiseHolder.class), "getValue", "(DDD)D", false);
m.astore(Type.DOUBLE_TYPE);
});
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.load(res1, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(Type.getInternalName(ArrayCache.class), "recycle", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(double[].class)}), false);
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.load(res2, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(Type.getInternalName(ArrayCache.class), "recycle", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(double[].class)}), false);
m.areturn(Type.VOID_TYPE);
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
ShiftedNoiseNode that = (ShiftedNoiseNode)o;
return Double.compare(this.xzScale, that.xzScale) == 0 && Double.compare(this.yScale, that.yScale) == 0 && Objects.equals(this.shiftX, that.shiftX) && Objects.equals(this.shiftY, that.shiftY) && Objects.equals(this.shiftZ, that.shiftZ) && Objects.equals(this.noise, that.noise);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
result = 31 * result + this.shiftX.hashCode();
result = 31 * result + this.shiftY.hashCode();
result = 31 * result + this.shiftZ.hashCode();
result = 31 * result + Double.hashCode(this.xzScale);
result = 31 * result + Double.hashCode(this.yScale);
result = 31 * result + this.noise.hashCode();
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
ShiftedNoiseNode that = (ShiftedNoiseNode)o;
return Double.compare(this.xzScale, that.xzScale) == 0 && Double.compare(this.yScale, that.yScale) == 0 && this.shiftX.relaxedEquals(that.shiftX) && this.shiftY.relaxedEquals(that.shiftY) && this.shiftZ.relaxedEquals(that.shiftZ);
} else {
return false;
}
}
public int relaxedHashCode() {
int result = 1;
result = 31 * result + this.shiftX.relaxedHashCode();
result = 31 * result + this.shiftY.relaxedHashCode();
result = 31 * result + this.shiftZ.relaxedHashCode();
result = 31 * result + Double.hashCode(this.xzScale);
result = 31 * result + Double.hashCode(this.yScale);
return result;
}
}

View File

@@ -0,0 +1,453 @@
package com.ishland.c2me.opts.dfc.common.ast.spline;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.ast.McToAst;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import com.ishland.c2me.opts.dfc.common.vif.NoisePosVanillaInterface;
import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.IntObjectPair;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import net.minecraft.util.CubicSpline;
import net.minecraft.util.Mth;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.DensityFunctions;
import com.ishland.flowsched.util.Assertions;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.AnalyzerAdapter;
import org.objectweb.asm.commons.InstructionAdapter;
public class SplineAstNode implements AstNode {
public static final String SPLINE_METHOD_DESC;
private final CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> spline;
public SplineAstNode(CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> spline) {
this.spline = spline;
}
public double evalSingle(int x, int y, int z, EvalType type) {
return (double)this.spline.apply(new DensityFunctions.Spline.Point(new NoisePosVanillaInterface(x, y, z, type)));
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
for(int i = 0; i < res.length; ++i) {
res[i] = this.evalSingle(x[i], y[i], z[i], type);
}
}
public AstNode[] getChildren() {
return new AstNode[0];
}
public AstNode transform(AstTransformer transformer) {
return transformer.transform(this);
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
ValuesMethodDef splineMethod = doBytecodeGenSpline(context, this.spline);
callSplineSingle(context, m, splineMethod);
m.cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
private static ValuesMethodDef doBytecodeGenSpline(BytecodeGen.Context context, CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> spline) {
String name = context.getCachedSplineMethod(spline);
if (name != null) {
return new ValuesMethodDef(false, name, 0.0F);
} else if (spline instanceof CubicSpline.Constant) {
CubicSpline.Constant<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> spline1 = (CubicSpline.Constant)spline;
return new ValuesMethodDef(true, (String)null, spline1.value());
} else {
name = context.nextMethodName("Spline");
InstructionAdapter m = new InstructionAdapter(new AnalyzerAdapter(context.className, 18, name, SPLINE_METHOD_DESC, context.classWriter.visitMethod(18, name, SPLINE_METHOD_DESC, (String)null, (String[])null)));
List<IntObjectPair<Pair<String, String>>> extraLocals = new ArrayList();
Label start = new Label();
Label end = new Label();
m.visitLabel(start);
BytecodeGen.Context.LocalVarConsumer localVarConsumer = (localName, localDesc) -> {
int ordinal = extraLocals.size() + 5;
extraLocals.add(IntObjectPair.of(ordinal, Pair.of(localName, localDesc)));
return ordinal;
};
if (spline instanceof CubicSpline.Multipoint) {
CubicSpline.Multipoint<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> impl = (CubicSpline.Multipoint)spline;
ValuesMethodDef[] valuesMethods = (ValuesMethodDef[])impl.values().stream().map((spline1x) -> {
return doBytecodeGenSpline(context, spline1x);
}).toArray((x$0) -> {
return new ValuesMethodDef[x$0];
});
String locations = context.newField(float[].class, impl.locations());
String derivatives = context.newField(float[].class, impl.derivatives());
int point = localVarConsumer.createLocalVariable("point", Type.FLOAT_TYPE.getDescriptor());
int rangeForLocation = localVarConsumer.createLocalVariable("rangeForLocation", Type.INT_TYPE.getDescriptor());
int lastConst = impl.locations().length - 1;
String locationFunction = context.newSingleMethod(McToAst.toAst((DensityFunction)((DensityFunctions.Spline.Coordinate)impl.coordinate()).function().value()));
context.callDelegateSingle(m, locationFunction);
m.cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
m.store(point, Type.FLOAT_TYPE);
if (valuesMethods.length == 1) {
m.load(point, Type.FLOAT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, locations, Type.getDescriptor(float[].class));
callSplineSingle(context, m, valuesMethods[0]);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, derivatives, Type.getDescriptor(float[].class));
m.iconst(0);
m.invokestatic(Type.getInternalName(SplineSupport.class), "sampleOutsideRange", Type.getMethodDescriptor(Type.FLOAT_TYPE, new Type[]{Type.FLOAT_TYPE, Type.getType(float[].class), Type.FLOAT_TYPE, Type.getType(float[].class), Type.INT_TYPE}), false);
m.areturn(Type.FLOAT_TYPE);
} else {
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, locations, Type.getDescriptor(float[].class));
m.load(point, Type.FLOAT_TYPE);
m.invokestatic(Type.getInternalName(SplineSupport.class), "findRangeForLocation", Type.getMethodDescriptor(Type.INT_TYPE, new Type[]{Type.getType(float[].class), Type.FLOAT_TYPE}), false);
m.store(rangeForLocation, Type.INT_TYPE);
Label label1 = new Label();
Label label2 = new Label();
m.load(rangeForLocation, Type.INT_TYPE);
m.ifge(label1);
m.load(point, Type.FLOAT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, locations, Type.getDescriptor(float[].class));
callSplineSingle(context, m, valuesMethods[0]);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, derivatives, Type.getDescriptor(float[].class));
m.iconst(0);
m.invokestatic(Type.getInternalName(SplineSupport.class), "sampleOutsideRange", Type.getMethodDescriptor(Type.FLOAT_TYPE, new Type[]{Type.FLOAT_TYPE, Type.getType(float[].class), Type.FLOAT_TYPE, Type.getType(float[].class), Type.INT_TYPE}), false);
m.areturn(Type.FLOAT_TYPE);
m.visitLabel(label1);
m.load(rangeForLocation, Type.INT_TYPE);
m.iconst(lastConst);
m.ificmpne(label2);
m.load(point, Type.FLOAT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, locations, Type.getDescriptor(float[].class));
callSplineSingle(context, m, valuesMethods[lastConst]);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, derivatives, Type.getDescriptor(float[].class));
m.iconst(lastConst);
m.invokestatic(Type.getInternalName(SplineSupport.class), "sampleOutsideRange", Type.getMethodDescriptor(Type.FLOAT_TYPE, new Type[]{Type.FLOAT_TYPE, Type.getType(float[].class), Type.FLOAT_TYPE, Type.getType(float[].class), Type.INT_TYPE}), false);
m.areturn(Type.FLOAT_TYPE);
m.visitLabel(label2);
int loc0 = localVarConsumer.createLocalVariable("loc0", Type.FLOAT_TYPE.getDescriptor());
int loc1 = localVarConsumer.createLocalVariable("loc1", Type.FLOAT_TYPE.getDescriptor());
int locDist = localVarConsumer.createLocalVariable("locDist", Type.FLOAT_TYPE.getDescriptor());
int k = localVarConsumer.createLocalVariable("k", Type.FLOAT_TYPE.getDescriptor());
int n = localVarConsumer.createLocalVariable("n", Type.FLOAT_TYPE.getDescriptor());
int o = localVarConsumer.createLocalVariable("o", Type.FLOAT_TYPE.getDescriptor());
int onDist = localVarConsumer.createLocalVariable("onDist", Type.FLOAT_TYPE.getDescriptor());
int p = localVarConsumer.createLocalVariable("p", Type.FLOAT_TYPE.getDescriptor());
int q = localVarConsumer.createLocalVariable("q", Type.FLOAT_TYPE.getDescriptor());
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, locations, Type.getDescriptor(float[].class));
m.load(rangeForLocation, Type.INT_TYPE);
m.aload(Type.FLOAT_TYPE);
m.store(loc0, Type.FLOAT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, locations, Type.getDescriptor(float[].class));
m.load(rangeForLocation, Type.INT_TYPE);
m.iconst(1);
m.add(Type.INT_TYPE);
m.aload(Type.FLOAT_TYPE);
m.store(loc1, Type.FLOAT_TYPE);
m.load(loc1, Type.FLOAT_TYPE);
m.load(loc0, Type.FLOAT_TYPE);
m.sub(Type.FLOAT_TYPE);
m.store(locDist, Type.FLOAT_TYPE);
m.load(point, Type.FLOAT_TYPE);
m.load(loc0, Type.FLOAT_TYPE);
m.sub(Type.FLOAT_TYPE);
m.load(locDist, Type.FLOAT_TYPE);
m.div(Type.FLOAT_TYPE);
m.store(k, Type.FLOAT_TYPE);
Label[] jumpLabels = new Label[valuesMethods.length - 1];
boolean[] jumpGenerated = new boolean[valuesMethods.length - 1];
for(int i = 0; i < valuesMethods.length - 1; ++i) {
jumpLabels[i] = new Label();
}
Label defaultLabel = new Label();
Label label3 = new Label();
m.load(rangeForLocation, Type.INT_TYPE);
m.tableswitch(0, valuesMethods.length - 2, defaultLabel, jumpLabels);
for(int i = 0; i < valuesMethods.length - 1; ++i) {
if (!jumpGenerated[i]) {
m.visitLabel(jumpLabels[i]);
jumpGenerated[i] = true;
for(int j = i + 1; j < valuesMethods.length - 1; ++j) {
if (valuesMethods[i].equals(valuesMethods[j]) && valuesMethods[i + 1].equals(valuesMethods[j + 1])) {
m.visitLabel(jumpLabels[j]);
jumpGenerated[j] = true;
}
}
callSplineSingle(context, m, valuesMethods[i]);
if (valuesMethods[i].equals(valuesMethods[i + 1])) {
m.dup();
m.store(n, Type.FLOAT_TYPE);
m.store(o, Type.FLOAT_TYPE);
} else {
m.store(n, Type.FLOAT_TYPE);
callSplineSingle(context, m, valuesMethods[i + 1]);
m.store(o, Type.FLOAT_TYPE);
}
m.goTo(label3);
}
}
m.visitLabel(defaultLabel);
m.iconst(0);
m.aconst("boom");
m.invokestatic(Type.getInternalName(Assertions.class), "assertTrue", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.BOOLEAN_TYPE, Type.getType(String.class)}), false);
m.fconst(Float.NaN);
m.areturn(Type.FLOAT_TYPE);
m.visitLabel(label3);
m.load(o, Type.FLOAT_TYPE);
m.load(n, Type.FLOAT_TYPE);
m.sub(Type.FLOAT_TYPE);
m.store(onDist, Type.FLOAT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, derivatives, Type.getDescriptor(float[].class));
m.load(rangeForLocation, Type.INT_TYPE);
m.aload(Type.FLOAT_TYPE);
m.load(locDist, Type.FLOAT_TYPE);
m.mul(Type.FLOAT_TYPE);
m.load(onDist, Type.FLOAT_TYPE);
m.sub(Type.FLOAT_TYPE);
m.store(p, Type.FLOAT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, derivatives, Type.getDescriptor(float[].class));
m.load(rangeForLocation, Type.INT_TYPE);
m.iconst(1);
m.add(Type.INT_TYPE);
m.aload(Type.FLOAT_TYPE);
m.neg(Type.FLOAT_TYPE);
m.load(locDist, Type.FLOAT_TYPE);
m.mul(Type.FLOAT_TYPE);
m.load(onDist, Type.FLOAT_TYPE);
m.add(Type.FLOAT_TYPE);
m.store(q, Type.FLOAT_TYPE);
m.load(k, Type.FLOAT_TYPE);
m.load(n, Type.FLOAT_TYPE);
m.load(o, Type.FLOAT_TYPE);
m.invokestatic(Type.getInternalName(Mth.class), "lerp", "(FFF)F", false);
m.load(k, Type.FLOAT_TYPE);
m.fconst(1.0F);
m.load(k, Type.FLOAT_TYPE);
m.sub(Type.FLOAT_TYPE);
m.mul(Type.FLOAT_TYPE);
m.load(k, Type.FLOAT_TYPE);
m.load(p, Type.FLOAT_TYPE);
m.load(q, Type.FLOAT_TYPE);
m.invokestatic(Type.getInternalName(Mth.class), "lerp", "(FFF)F", false);
m.mul(Type.FLOAT_TYPE);
m.add(Type.FLOAT_TYPE);
m.areturn(Type.FLOAT_TYPE);
}
} else {
if (!(spline instanceof CubicSpline.Constant)) {
throw new UnsupportedOperationException(String.format("Unsupported spline implementation: %s", spline.getClass().getName()));
}
CubicSpline.Constant<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> floatFunction = (CubicSpline.Constant)spline;
m.fconst(floatFunction.value());
m.areturn(Type.FLOAT_TYPE);
}
m.visitLabel(end);
m.visitLocalVariable("this", context.classDesc, (String)null, start, end, 0);
m.visitLocalVariable("x", Type.INT_TYPE.getDescriptor(), (String)null, start, end, 1);
m.visitLocalVariable("y", Type.INT_TYPE.getDescriptor(), (String)null, start, end, 2);
m.visitLocalVariable("z", Type.INT_TYPE.getDescriptor(), (String)null, start, end, 3);
m.visitLocalVariable("evalType", Type.getType(EvalType.class).getDescriptor(), (String)null, start, end, 4);
Iterator var35 = extraLocals.iterator();
while(var35.hasNext()) {
IntObjectPair<Pair<String, String>> local = (IntObjectPair)var35.next();
m.visitLocalVariable((String)((Pair)local.right()).left(), (String)((Pair)local.right()).right(), (String)null, start, end, local.leftInt());
}
m.visitMaxs(0, 0);
context.cacheSplineMethod(spline, name);
return new ValuesMethodDef(false, name, 0.0F);
}
}
private static void callSplineSingle(BytecodeGen.Context context, InstructionAdapter m, ValuesMethodDef target) {
if (target.isConst()) {
m.fconst(target.constValue());
} else {
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(1, Type.INT_TYPE);
m.load(2, Type.INT_TYPE);
m.load(3, Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, target.generatedMethod(), SPLINE_METHOD_DESC, false);
}
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
context.delegateToSingle(m, localVarConsumer, this);
m.areturn(Type.VOID_TYPE);
}
private static boolean deepEquals(CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a, CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> b) {
if (a instanceof CubicSpline.Constant<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a1) {
if (b instanceof CubicSpline.Constant<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> b1) {
return a1.value() == b1.value();
}
}
if (a instanceof CubicSpline.Multipoint<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a1) {
if (b instanceof CubicSpline.Multipoint<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> b1) {
boolean equals1 = Arrays.equals(a1.derivatives(), b1.derivatives()) && Arrays.equals(a1.locations(), b1.locations()) && a1.values().size() == b1.values().size() && McToAst.toAst((DensityFunction)((DensityFunctions.Spline.Coordinate)a1.coordinate()).function().value()).equals(McToAst.toAst((DensityFunction)((DensityFunctions.Spline.Coordinate)b1.coordinate()).function().value()));
if (!equals1) {
return false;
}
int size = a1.values().size();
for(int i = 0; i < size; ++i) {
if (!deepEquals((CubicSpline)a1.values().get(i), (CubicSpline)b1.values().get(i))) {
return false;
}
}
return true;
}
}
return false;
}
private static boolean deepRelaxedEquals(CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a, CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> b) {
if (a instanceof CubicSpline.Constant<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a1) {
if (b instanceof CubicSpline.Constant<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> b1) {
return a1.value() == b1.value();
}
}
if (a instanceof CubicSpline.Multipoint<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a1) {
if (b instanceof CubicSpline.Multipoint<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> b1) {
boolean equals1 = a1.values().size() == b1.values().size() && McToAst.toAst((DensityFunction)((DensityFunctions.Spline.Coordinate)a1.coordinate()).function().value()).relaxedEquals(McToAst.toAst((DensityFunction)((DensityFunctions.Spline.Coordinate)b1.coordinate()).function().value()));
if (!equals1) {
return false;
}
int size = a1.values().size();
for(int i = 0; i < size; ++i) {
if (!deepRelaxedEquals((CubicSpline)a1.values().get(i), (CubicSpline)b1.values().get(i))) {
return false;
}
}
return true;
}
}
return false;
}
private static int deepHashcode(CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a) {
if (a instanceof CubicSpline.Constant<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a1) {
return Float.hashCode(a1.value());
} else if (!(a instanceof CubicSpline.Multipoint<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a1)) {
return a.hashCode();
} else {
int result = 1;
result = 31 * result + Arrays.hashCode(a1.derivatives());
result = 31 * result + Arrays.hashCode(a1.locations());
CubicSpline spline;
for(Iterator var4 = a1.values().iterator(); var4.hasNext(); result = 31 * result + deepHashcode(spline)) {
spline = (CubicSpline)var4.next();
}
result = 31 * result + McToAst.toAst((DensityFunction)((DensityFunctions.Spline.Coordinate)a1.coordinate()).function().value()).hashCode();
return result;
}
}
private static int deepRelaxedHashcode(CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a) {
if (a instanceof CubicSpline.Constant<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a1) {
return Float.hashCode(a1.value());
} else if (!(a instanceof CubicSpline.Multipoint<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> a1)) {
return a.hashCode();
} else {
int result = 1;
CubicSpline spline;
for(Iterator var4 = a1.values().iterator(); var4.hasNext(); result = 31 * result + deepRelaxedHashcode(spline)) {
spline = (CubicSpline)var4.next();
}
result = 31 * result + McToAst.toAst((DensityFunction)((DensityFunctions.Spline.Coordinate)a1.coordinate()).function().value()).relaxedHashCode();
return result;
}
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
SplineAstNode that = (SplineAstNode)o;
return deepEquals(this.spline, that.spline);
} else {
return false;
}
}
public int hashCode() {
return deepHashcode(this.spline);
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
SplineAstNode that = (SplineAstNode)o;
return deepRelaxedEquals(this.spline, that.spline);
} else {
return false;
}
}
public int relaxedHashCode() {
return deepRelaxedHashcode(this.spline);
}
static {
SPLINE_METHOD_DESC = Type.getMethodDescriptor(Type.getType(Float.TYPE), new Type[]{Type.getType(Integer.TYPE), Type.getType(Integer.TYPE), Type.getType(Integer.TYPE), Type.getType(EvalType.class)});
}
private static record ValuesMethodDef(boolean isConst, String generatedMethod, float constValue) {
private ValuesMethodDef(boolean isConst, String generatedMethod, float constValue) {
this.isConst = isConst;
this.generatedMethod = generatedMethod;
this.constValue = constValue;
}
public boolean isConst() {
return this.isConst;
}
public String generatedMethod() {
return this.generatedMethod;
}
public float constValue() {
return this.constValue;
}
}
}

View File

@@ -0,0 +1,29 @@
package com.ishland.c2me.opts.dfc.common.ast.spline;
public class SplineSupport {
public SplineSupport() {
}
public static int findRangeForLocation(float[] locations, float x) {
int min = 0;
int i = locations.length;
while(i > 0) {
int j = i / 2;
int k = min + j;
if (x < locations[k]) {
i = j;
} else {
min = k + 1;
i -= j + 1;
}
}
return min - 1;
}
public static float sampleOutsideRange(float point, float[] locations, float value, float[] derivatives, int i) {
float f = derivatives[i];
return f == 0.0F ? value : value + f * (point - locations[i]);
}
}

View File

@@ -0,0 +1,49 @@
package com.ishland.c2me.opts.dfc.common.ast.unary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class AbsNode extends AbstractUnaryNode {
public AbsNode(AstNode operand) {
super(operand);
}
protected AstNode newInstance(AstNode operand) {
return new AbsNode(operand);
}
public double evalSingle(int x, int y, int z, EvalType type) {
return Math.abs(this.operand.evalSingle(x, y, z, type));
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.operand.evalMulti(res, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
res[i] = Math.abs(res[i]);
}
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenSingle(context, m, localVarConsumer);
m.invokestatic(Type.getInternalName(Math.class), "abs", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE}), false);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenMulti(context, m, localVarConsumer);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.dup2();
m.aload(Type.DOUBLE_TYPE);
m.invokestatic(Type.getInternalName(Math.class), "abs", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE}), false);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
}

View File

@@ -0,0 +1,72 @@
package com.ishland.c2me.opts.dfc.common.ast.unary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.AstTransformer;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import java.util.Objects;
import org.objectweb.asm.commons.InstructionAdapter;
public abstract class AbstractUnaryNode implements AstNode {
protected final AstNode operand;
public AbstractUnaryNode(AstNode operand) {
this.operand = (AstNode)Objects.requireNonNull(operand);
}
public AstNode[] getChildren() {
return new AstNode[]{this.operand};
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
AbstractUnaryNode that = (AbstractUnaryNode)o;
return Objects.equals(this.operand, that.operand);
} else {
return false;
}
}
public int hashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.operand.hashCode();
return result;
}
public boolean relaxedEquals(AstNode o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
AbstractUnaryNode that = (AbstractUnaryNode)o;
return this.operand.relaxedEquals(that.operand);
} else {
return false;
}
}
public int relaxedHashCode() {
int result = 1;
result = 31 * result + this.getClass().hashCode();
result = 31 * result + this.operand.relaxedHashCode();
return result;
}
protected abstract AstNode newInstance(AstNode var1);
public AstNode transform(AstTransformer transformer) {
AstNode operand = this.operand.transform(transformer);
return this.operand == operand ? transformer.transform(this) : transformer.transform(this.newInstance(operand));
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String operandMethod = context.newSingleMethod(this.operand);
context.callDelegateSingle(m, operandMethod);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
String operandMethod = context.newMultiMethod(this.operand);
context.callDelegateMulti(m, operandMethod);
}
}

View File

@@ -0,0 +1,56 @@
package com.ishland.c2me.opts.dfc.common.ast.unary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class CubeNode extends AbstractUnaryNode {
public CubeNode(AstNode operand) {
super(operand);
}
protected AstNode newInstance(AstNode operand) {
return new CubeNode(operand);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double v = this.operand.evalSingle(x, y, z, type);
return v * v * v;
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.operand.evalMulti(res, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
res[i] = res[i] * res[i] * res[i];
}
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenSingle(context, m, localVarConsumer);
m.dup2();
m.dup2();
m.mul(Type.DOUBLE_TYPE);
m.mul(Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenMulti(context, m, localVarConsumer);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.dup2();
m.aload(Type.DOUBLE_TYPE);
m.dup2();
m.dup2();
m.mul(Type.DOUBLE_TYPE);
m.mul(Type.DOUBLE_TYPE);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
}

View File

@@ -0,0 +1,83 @@
package com.ishland.c2me.opts.dfc.common.ast.unary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class NegMulNode extends AbstractUnaryNode {
private final double negMul;
public NegMulNode(AstNode operand, double negMul) {
super(operand);
this.negMul = negMul;
}
protected AstNode newInstance(AstNode operand) {
return new NegMulNode(operand, this.negMul);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double v = this.operand.evalSingle(x, y, z, type);
return v > 0.0 ? v : v * this.negMul;
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.operand.evalMulti(res, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
double v = res[i];
res[i] = v > 0.0 ? v : v * this.negMul;
}
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenSingle(context, m, localVarConsumer);
int v = localVarConsumer.createLocalVariable("v", Type.DOUBLE_TYPE.getDescriptor());
m.store(v, Type.DOUBLE_TYPE);
Label negMulLabel = new Label();
Label end = new Label();
m.load(v, Type.DOUBLE_TYPE);
m.dconst(0.0);
m.cmpl(Type.DOUBLE_TYPE);
m.ifle(negMulLabel);
m.load(v, Type.DOUBLE_TYPE);
m.goTo(end);
m.visitLabel(negMulLabel);
m.load(v, Type.DOUBLE_TYPE);
m.dconst(this.negMul);
m.mul(Type.DOUBLE_TYPE);
m.visitLabel(end);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenMulti(context, m, localVarConsumer);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
int v = localVarConsumer.createLocalVariable("v", Type.DOUBLE_TYPE.getDescriptor());
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.dup2();
m.aload(Type.DOUBLE_TYPE);
m.store(v, Type.DOUBLE_TYPE);
Label negMulLabel = new Label();
Label end = new Label();
m.load(v, Type.DOUBLE_TYPE);
m.dconst(0.0);
m.cmpl(Type.DOUBLE_TYPE);
m.ifle(negMulLabel);
m.load(v, Type.DOUBLE_TYPE);
m.goTo(end);
m.visitLabel(negMulLabel);
m.load(v, Type.DOUBLE_TYPE);
m.dconst(this.negMul);
m.mul(Type.DOUBLE_TYPE);
m.visitLabel(end);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
}

View File

@@ -0,0 +1,52 @@
package com.ishland.c2me.opts.dfc.common.ast.unary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class SquareNode extends AbstractUnaryNode {
public SquareNode(AstNode operand) {
super(operand);
}
protected AstNode newInstance(AstNode operand) {
return new SquareNode(operand);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double v = this.operand.evalSingle(x, y, z, type);
return v * v;
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.operand.evalMulti(res, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
res[i] *= res[i];
}
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenSingle(context, m, localVarConsumer);
m.dup2();
m.mul(Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenMulti(context, m, localVarConsumer);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.dup2();
m.aload(Type.DOUBLE_TYPE);
m.dup2();
m.mul(Type.DOUBLE_TYPE);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
}

View File

@@ -0,0 +1,84 @@
package com.ishland.c2me.opts.dfc.common.ast.unary;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.gen.BytecodeGen;
import net.minecraft.util.Mth;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
public class SqueezeNode extends AbstractUnaryNode {
public SqueezeNode(AstNode operand) {
super(operand);
}
protected AstNode newInstance(AstNode operand) {
return new SqueezeNode(operand);
}
public double evalSingle(int x, int y, int z, EvalType type) {
double v = Mth.clamp(this.operand.evalSingle(x, y, z, type), -1.0, 1.0);
return v / 2.0 - v * v * v / 24.0;
}
public void evalMulti(double[] res, int[] x, int[] y, int[] z, EvalType type) {
this.operand.evalMulti(res, x, y, z, type);
for(int i = 0; i < res.length; ++i) {
double v = Mth.clamp(res[i], -1.0, 1.0);
res[i] = v / 2.0 - v * v * v / 24.0;
}
}
public void doBytecodeGenSingle(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenSingle(context, m, localVarConsumer);
m.dconst(1.0);
m.invokestatic(Type.getInternalName(Math.class), "min", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.dconst(-1.0);
m.invokestatic(Type.getInternalName(Math.class), "max", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
int v = localVarConsumer.createLocalVariable("v", Type.DOUBLE_TYPE.getDescriptor());
m.store(v, Type.DOUBLE_TYPE);
m.load(v, Type.DOUBLE_TYPE);
m.dconst(2.0);
m.div(Type.DOUBLE_TYPE);
m.load(v, Type.DOUBLE_TYPE);
m.dup2();
m.dup2();
m.mul(Type.DOUBLE_TYPE);
m.mul(Type.DOUBLE_TYPE);
m.dconst(24.0);
m.div(Type.DOUBLE_TYPE);
m.sub(Type.DOUBLE_TYPE);
m.areturn(Type.DOUBLE_TYPE);
}
public void doBytecodeGenMulti(BytecodeGen.Context context, InstructionAdapter m, BytecodeGen.Context.LocalVarConsumer localVarConsumer) {
super.doBytecodeGenMulti(context, m, localVarConsumer);
context.doCountedLoop(m, localVarConsumer, (idx) -> {
int v = localVarConsumer.createLocalVariable("v", Type.DOUBLE_TYPE.getDescriptor());
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.dup2();
m.aload(Type.DOUBLE_TYPE);
m.dconst(1.0);
m.invokestatic(Type.getInternalName(Math.class), "min", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.dconst(-1.0);
m.invokestatic(Type.getInternalName(Math.class), "max", Type.getMethodDescriptor(Type.DOUBLE_TYPE, new Type[]{Type.DOUBLE_TYPE, Type.DOUBLE_TYPE}), false);
m.store(v, Type.DOUBLE_TYPE);
m.load(v, Type.DOUBLE_TYPE);
m.dconst(2.0);
m.div(Type.DOUBLE_TYPE);
m.load(v, Type.DOUBLE_TYPE);
m.dup2();
m.dup2();
m.mul(Type.DOUBLE_TYPE);
m.mul(Type.DOUBLE_TYPE);
m.dconst(24.0);
m.div(Type.DOUBLE_TYPE);
m.sub(Type.DOUBLE_TYPE);
m.astore(Type.DOUBLE_TYPE);
});
m.areturn(Type.VOID_TYPE);
}
}

View File

@@ -0,0 +1,7 @@
package com.ishland.c2me.opts.dfc.common.ducks;
import com.ishland.c2me.opts.dfc.common.util.ArrayCache;
public interface IArrayCacheCapable {
ArrayCache c2me$getArrayCache();
}

View File

@@ -0,0 +1,5 @@
package com.ishland.c2me.opts.dfc.common.ducks;
public interface IBlendingAwareVisitor {
boolean c2me$isBlendingEnabled();
}

View File

@@ -0,0 +1,5 @@
package com.ishland.c2me.opts.dfc.common.ducks;
public interface ICoordinatesFilling {
void c2me$fillCoordinates(int[] var1, int[] var2, int[] var3);
}

View File

@@ -0,0 +1,7 @@
package com.ishland.c2me.opts.dfc.common.ducks;
public interface IEqualityOverriding {
void c2me$overrideEquality(Object var1);
Object c2me$getOverriddenEquality();
}

View File

@@ -0,0 +1,20 @@
package com.ishland.c2me.opts.dfc.common.ducks;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import net.minecraft.world.level.levelgen.DensityFunction;
public interface IFastCacheLike extends DensityFunction {
long CACHE_MISS_NAN_BITS = 9222769054270909007L;
double c2me$getCached(int var1, int var2, int var3, EvalType var4);
boolean c2me$getCached(double[] var1, int[] var2, int[] var3, int[] var4, EvalType var5);
void c2me$cache(int var1, int var2, int var3, EvalType var4, double var5);
void c2me$cache(double[] var1, int[] var2, int[] var3, int[] var4, EvalType var5);
DensityFunction c2me$getDelegate();
DensityFunction c2me$withDelegate(DensityFunction var1);
}

View File

@@ -0,0 +1,499 @@
package com.ishland.c2me.opts.dfc.common.gen;
import com.google.common.io.Files;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.ast.McToAst;
import com.ishland.c2me.opts.dfc.common.ast.dfvisitor.StripBlending;
import com.ishland.c2me.opts.dfc.common.ast.misc.ConstantNode;
import com.ishland.c2me.opts.dfc.common.ast.misc.RootNode;
import com.ishland.c2me.opts.dfc.common.util.ArrayCache;
import com.ishland.c2me.opts.dfc.common.vif.AstVanillaInterface;
import it.unimi.dsi.fastutil.Hash;
import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.IntObjectPair;
import it.unimi.dsi.fastutil.objects.Object2ReferenceMap;
import it.unimi.dsi.fastutil.objects.Object2ReferenceMaps;
import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenCustomHashMap;
import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
import java.util.stream.Collectors;
import net.minecraft.util.CubicSpline;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.DensityFunctions;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.AnalyzerAdapter;
import org.objectweb.asm.commons.InstructionAdapter;
public class BytecodeGen {
private static final File exportDir = new File("./cache/c2me-dfc");
private static final AtomicLong ordinal = new AtomicLong();
public static final Hash.Strategy<AstNode> RELAXED_STRATEGY;
private static final Object2ReferenceMap<AstNode, Class<?>> compilationCache;
public BytecodeGen() {
}
public static DensityFunction compile(DensityFunction densityFunction, Reference2ReferenceMap<DensityFunction, DensityFunction> tempCache) {
DensityFunction cached = (DensityFunction)tempCache.get(densityFunction);
if (cached != null) {
return cached;
} else if (densityFunction instanceof AstVanillaInterface) {
AstVanillaInterface vif = (AstVanillaInterface)densityFunction;
AstNode ast = vif.getAstNode();
return new CompiledDensityFunction(compile0(ast), vif.getBlendingFallback());
} else {
AstNode ast = McToAst.toAst(densityFunction.mapAll(StripBlending.INSTANCE));
if (ast instanceof ConstantNode) {
ConstantNode constantNode = (ConstantNode)ast;
return DensityFunctions.constant(constantNode.getValue());
} else {
CompiledDensityFunction compiled = new CompiledDensityFunction(compile0(ast), densityFunction);
tempCache.put(densityFunction, compiled);
return compiled;
}
}
}
public static synchronized CompiledEntry compile0(AstNode node) {
Class<?> cached = (Class)compilationCache.get(node);
ClassWriter writer = new ClassWriter(3);
String name = cached != null ? String.format("DfcCompiled_discarded") : String.format("DfcCompiled_%d", ordinal.getAndIncrement());
writer.visit(65, 17, name, (String)null, Type.getInternalName(Object.class), new String[]{Type.getInternalName(CompiledEntry.class)});
RootNode rootNode = new RootNode(node);
Context genContext = new Context(writer, name);
genContext.newSingleMethod0((adapter, localVarConsumer) -> {
rootNode.doBytecodeGenSingle(genContext, adapter, localVarConsumer);
}, "evalSingle", true);
genContext.newMultiMethod0((adapter, localVarConsumer) -> {
rootNode.doBytecodeGenMulti(genContext, adapter, localVarConsumer);
}, "evalMulti", true);
List<Object> args = (List)genContext.args.entrySet().stream().sorted(Comparator.comparingInt((o) -> {
return ((Context.FieldRecord)o.getValue()).ordinal();
})).map(Map.Entry::getKey).collect(Collectors.toCollection(ArrayList::new));
if (cached != null) {
try {
return (CompiledEntry)cached.getConstructor(List.class).newInstance(args);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | InstantiationException var11) {
ReflectiveOperationException e = var11;
throw new RuntimeException(e);
}
} else {
genConstructor(genContext);
genGetArgs(genContext);
genNewInstance(genContext);
Object var8;
for(ListIterator<Object> iterator = args.listIterator(); iterator.hasNext(); var8 = iterator.next()) {
}
byte[] bytes = writer.toByteArray();
dumpClass(genContext.className, bytes);
Class<?> defined = defineClass(genContext.className, bytes);
compilationCache.put(node, defined);
try {
return (CompiledEntry)defined.getConstructor(List.class).newInstance(args);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException | InstantiationException var12) {
ReflectiveOperationException e = var12;
throw new RuntimeException(e);
}
}
}
private static void genConstructor(Context context) {
InstructionAdapter m = new InstructionAdapter(new AnalyzerAdapter(context.className, 1, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(List.class)}), context.classWriter.visitMethod(1, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(List.class)}), (String)null, (String[])null)));
Label start = new Label();
Label end = new Label();
m.visitLabel(start);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.invokespecial(Type.getInternalName(Object.class), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[0]), false);
Iterator var4 = context.args.entrySet().stream().sorted(Comparator.comparingInt((o) -> {
return ((Context.FieldRecord)o.getValue()).ordinal();
})).toList().iterator();
while(var4.hasNext()) {
Map.Entry<Object, Context.FieldRecord> entry = (Map.Entry)var4.next();
String name = ((Context.FieldRecord)entry.getValue()).name();
Class<?> type = ((Context.FieldRecord)entry.getValue()).type();
int ordinal = ((Context.FieldRecord)entry.getValue()).ordinal();
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.iconst(ordinal);
m.invokeinterface(Type.getInternalName(List.class), "get", Type.getMethodDescriptor(InstructionAdapter.OBJECT_TYPE, new Type[]{Type.INT_TYPE}));
m.checkcast(Type.getType(type));
m.putfield(context.className, name, Type.getDescriptor(type));
}
var4 = context.postProcessMethods.stream().sorted().toList().iterator();
while(var4.hasNext()) {
String postProcessingMethod = (String)var4.next();
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(context.className, postProcessingMethod, "()V", false);
}
m.areturn(Type.VOID_TYPE);
m.visitLabel(end);
m.visitLocalVariable("this", context.classDesc, (String)null, start, end, 0);
m.visitLocalVariable("list", Type.getDescriptor(List.class), (String)null, start, end, 1);
m.visitMaxs(0, 0);
}
private static void genGetArgs(Context context) {
InstructionAdapter m = new InstructionAdapter(new AnalyzerAdapter(context.className, 17, "getArgs", Type.getMethodDescriptor(Type.getType(List.class), new Type[0]), context.classWriter.visitMethod(17, "getArgs", Type.getMethodDescriptor(Type.getType(List.class), new Type[0]), (String)null, (String[])null)));
Label start = new Label();
Label end = new Label();
m.visitLabel(start);
m.anew(Type.getType(ArrayList.class));
m.dup();
m.iconst(context.args.size());
m.invokespecial(Type.getInternalName(ArrayList.class), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.INT_TYPE}), false);
m.store(1, InstructionAdapter.OBJECT_TYPE);
Iterator var4 = context.args.entrySet().stream().sorted(Comparator.comparingInt((o) -> {
return ((Context.FieldRecord)o.getValue()).ordinal();
})).toList().iterator();
while(var4.hasNext()) {
Map.Entry<Object, Context.FieldRecord> entry = (Map.Entry)var4.next();
String name = ((Context.FieldRecord)entry.getValue()).name();
Class<?> type = ((Context.FieldRecord)entry.getValue()).type();
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.getfield(context.className, name, Type.getDescriptor(type));
m.invokeinterface(Type.getInternalName(List.class), "add", Type.getMethodDescriptor(Type.BOOLEAN_TYPE, new Type[]{InstructionAdapter.OBJECT_TYPE}));
m.pop();
}
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.areturn(InstructionAdapter.OBJECT_TYPE);
m.visitLabel(end);
m.visitLocalVariable("this", context.classDesc, (String)null, start, end, 0);
m.visitLocalVariable("list", Type.getDescriptor(List.class), (String)null, start, end, 1);
m.visitMaxs(0, 0);
}
private static void genNewInstance(Context context) {
InstructionAdapter m = new InstructionAdapter(new AnalyzerAdapter(context.className, 17, "newInstance", Type.getMethodDescriptor(Type.getType(CompiledEntry.class), new Type[]{Type.getType(List.class)}), context.classWriter.visitMethod(17, "newInstance", Type.getMethodDescriptor(Type.getType(CompiledEntry.class), new Type[]{Type.getType(List.class)}), (String)null, (String[])null)));
Label start = new Label();
Label end = new Label();
m.visitLabel(start);
m.anew(Type.getType(context.classDesc));
m.dup();
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.invokespecial(context.className, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(List.class)}), false);
m.areturn(InstructionAdapter.OBJECT_TYPE);
m.visitLabel(end);
m.visitLocalVariable("this", context.classDesc, (String)null, start, end, 0);
m.visitLocalVariable("list", Type.getDescriptor(List.class), (String)null, start, end, 1);
m.visitMaxs(0, 0);
}
private static void dumpClass(String className, byte[] bytes) {
File outputFile = new File(exportDir, className + ".class");
outputFile.getParentFile().mkdirs();
try {
Files.write(bytes, outputFile);
} catch (IOException var4) {
IOException e = var4;
e.printStackTrace();
}
}
private static Class<?> defineClass(final String className, final byte[] bytes) {
ClassLoader classLoader = new ClassLoader(BytecodeGen.class.getClassLoader()) {
public Class<?> loadClass(String name) throws ClassNotFoundException {
return name.equals(className) ? super.defineClass(name, bytes, 0, bytes.length) : super.loadClass(name);
}
};
try {
return classLoader.loadClass(className);
} catch (ClassNotFoundException var4) {
ClassNotFoundException e = var4;
throw new RuntimeException(e);
}
}
static {
try {
com.ishland.c2me.opts.dfc.util.Files.deleteRecursively(exportDir);
} catch (IOException var1) {
IOException e = var1;
e.printStackTrace();
}
RELAXED_STRATEGY = new Hash.Strategy<AstNode>() {
public int hashCode(AstNode o) {
return o.relaxedHashCode();
}
public boolean equals(AstNode a, AstNode b) {
return a.relaxedEquals(b);
}
};
compilationCache = Object2ReferenceMaps.synchronize(new Object2ReferenceOpenCustomHashMap<>(RELAXED_STRATEGY));
}
public static class Context {
public static final String SINGLE_DESC;
public static final String MULTI_DESC;
public final ClassWriter classWriter;
public final String className;
public final String classDesc;
private int methodIdx = 0;
private final Object2ReferenceOpenHashMap<AstNode, String> singleMethods = new Object2ReferenceOpenHashMap<>();
private final Object2ReferenceOpenHashMap<AstNode, String> multiMethods = new Object2ReferenceOpenHashMap<>();
private final Object2ReferenceOpenHashMap<CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate>, String> splineMethods = new Object2ReferenceOpenHashMap<>();
private final ObjectOpenHashSet<String> postProcessMethods = new ObjectOpenHashSet<>();
private final Reference2ObjectOpenHashMap<Object, FieldRecord> args = new Reference2ObjectOpenHashMap<>();
public Context(ClassWriter classWriter, String className) {
this.classWriter = (ClassWriter)Objects.requireNonNull(classWriter);
this.className = (String)Objects.requireNonNull(className);
this.classDesc = String.format("L%s;", this.className);
}
public String nextMethodName() {
return String.format("method_%d", this.methodIdx++);
}
public String nextMethodName(String suffix) {
return String.format("method_%d_%s", this.methodIdx++, suffix);
}
public String newSingleMethod(AstNode node) {
return this.singleMethods.computeIfAbsent(node, (AstNode node1) -> this.newSingleMethod((adapter, localVarConsumer) -> node1.doBytecodeGenSingle(this, adapter, localVarConsumer), nextMethodName(node.getClass().getSimpleName())));
}
public String newSingleMethod(BiConsumer<InstructionAdapter, LocalVarConsumer> generator) {
return this.newSingleMethod(generator, this.nextMethodName());
}
public String newSingleMethod(BiConsumer<InstructionAdapter, LocalVarConsumer> generator, String name) {
this.newSingleMethod0(generator, name, false);
return name;
}
private void newSingleMethod0(BiConsumer<InstructionAdapter, LocalVarConsumer> generator, String name, boolean isPublic) {
InstructionAdapter adapter = new InstructionAdapter(new AnalyzerAdapter(this.className, (isPublic ? 1 : 2) | 16, name, SINGLE_DESC, this.classWriter.visitMethod((isPublic ? 1 : 2) | 16, name, SINGLE_DESC, (String)null, (String[])null)));
List<IntObjectPair<Pair<String, String>>> extraLocals = new ArrayList<>();
Label start = new Label();
Label end = new Label();
adapter.visitLabel(start);
generator.accept(adapter, (localName, localDesc) -> {
int ordinal = extraLocals.size() + 5;
extraLocals.add(IntObjectPair.of(ordinal, Pair.of(localName, localDesc)));
return ordinal;
});
adapter.visitLabel(end);
adapter.visitLocalVariable("this", this.classDesc, (String)null, start, end, 0);
adapter.visitLocalVariable("x", Type.INT_TYPE.getDescriptor(), (String)null, start, end, 1);
adapter.visitLocalVariable("y", Type.INT_TYPE.getDescriptor(), (String)null, start, end, 2);
adapter.visitLocalVariable("z", Type.INT_TYPE.getDescriptor(), (String)null, start, end, 3);
adapter.visitLocalVariable("evalType", Type.getType(EvalType.class).getDescriptor(), (String)null, start, end, 4);
Iterator var8 = extraLocals.iterator();
while(var8.hasNext()) {
IntObjectPair<Pair<String, String>> local = (IntObjectPair)var8.next();
adapter.visitLocalVariable((String)((Pair)local.right()).left(), (String)((Pair)local.right()).right(), (String)null, start, end, local.leftInt());
}
adapter.visitMaxs(0, 0);
}
public String newMultiMethod(AstNode node) {
return this.multiMethods.computeIfAbsent(node, (AstNode node1) -> this.newMultiMethod((adapter, localVarConsumer) -> node1.doBytecodeGenMulti(this, adapter, localVarConsumer), nextMethodName(node.getClass().getSimpleName())));
}
public String newMultiMethod(BiConsumer<InstructionAdapter, LocalVarConsumer> generator) {
return this.newMultiMethod(generator, this.nextMethodName());
}
public String newMultiMethod(BiConsumer<InstructionAdapter, LocalVarConsumer> generator, String name) {
this.newMultiMethod0(generator, name, false);
return name;
}
private void newMultiMethod0(BiConsumer<InstructionAdapter, LocalVarConsumer> generator, String name, boolean isPublic) {
InstructionAdapter adapter = new InstructionAdapter(new AnalyzerAdapter(this.className, (isPublic ? 1 : 2) | 16, name, MULTI_DESC, this.classWriter.visitMethod((isPublic ? 1 : 2) | 16, name, MULTI_DESC, (String)null, (String[])null)));
List<IntObjectPair<Pair<String, String>>> extraLocals = new ArrayList();
Label start = new Label();
Label end = new Label();
adapter.visitLabel(start);
generator.accept(adapter, (localName, localDesc) -> {
int ordinal = extraLocals.size() + 7;
extraLocals.add(IntObjectPair.of(ordinal, Pair.of(localName, localDesc)));
return ordinal;
});
adapter.visitLabel(end);
adapter.visitLocalVariable("this", this.classDesc, (String)null, start, end, 0);
adapter.visitLocalVariable("res", Type.getType(double[].class).getDescriptor(), (String)null, start, end, 1);
adapter.visitLocalVariable("x", Type.getType(double[].class).getDescriptor(), (String)null, start, end, 2);
adapter.visitLocalVariable("y", Type.getType(double[].class).getDescriptor(), (String)null, start, end, 3);
adapter.visitLocalVariable("z", Type.getType(double[].class).getDescriptor(), (String)null, start, end, 4);
adapter.visitLocalVariable("evalType", Type.getType(EvalType.class).getDescriptor(), (String)null, start, end, 5);
adapter.visitLocalVariable("arrayCache", Type.getType(ArrayCache.class).getDescriptor(), (String)null, start, end, 6);
Iterator var8 = extraLocals.iterator();
while(var8.hasNext()) {
IntObjectPair<Pair<String, String>> local = (IntObjectPair)var8.next();
adapter.visitLocalVariable((String)((Pair)local.right()).left(), (String)((Pair)local.right()).right(), (String)null, start, end, local.leftInt());
}
adapter.visitMaxs(0, 0);
}
public String getCachedSplineMethod(CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> spline) {
return (String)this.splineMethods.get(spline);
}
public void cacheSplineMethod(CubicSpline<DensityFunctions.Spline.Point, DensityFunctions.Spline.Coordinate> spline, String method) {
this.splineMethods.put(spline, method);
}
public void callDelegateSingle(InstructionAdapter m, String target) {
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(1, Type.INT_TYPE);
m.load(2, Type.INT_TYPE);
m.load(3, Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(this.className, target, SINGLE_DESC, false);
}
public void callDelegateMulti(InstructionAdapter m, String target) {
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.load(6, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(this.className, target, MULTI_DESC, false);
}
public <T> String newField(Class<T> type, T data) {
FieldRecord existing = (FieldRecord)this.args.get(data);
if (existing != null) {
return existing.name();
} else {
int size = this.args.size();
String name = String.format("field_%d", size);
this.classWriter.visitField(2, name, Type.getDescriptor(type), (String)null, (Object)null);
this.args.put(data, new FieldRecord(name, size, type));
return name;
}
}
public void doCountedLoop(InstructionAdapter m, LocalVarConsumer localVarConsumer, IntConsumer bodyGenerator) {
int loopIdx = localVarConsumer.createLocalVariable("loopIdx", Type.INT_TYPE.getDescriptor());
m.iconst(0);
m.store(loopIdx, Type.INT_TYPE);
Label start = new Label();
Label end = new Label();
m.visitLabel(start);
m.load(loopIdx, Type.INT_TYPE);
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.arraylength();
m.ificmpge(end);
bodyGenerator.accept(loopIdx);
m.iinc(loopIdx, 1);
m.goTo(start);
m.visitLabel(end);
}
public void delegateToSingle(InstructionAdapter m, LocalVarConsumer localVarConsumer, AstNode current) {
String singleMethod = this.newSingleMethod(current);
this.doCountedLoop(m, localVarConsumer, (idx) -> {
m.load(1, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.load(0, InstructionAdapter.OBJECT_TYPE);
m.load(2, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(3, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(4, InstructionAdapter.OBJECT_TYPE);
m.load(idx, Type.INT_TYPE);
m.aload(Type.INT_TYPE);
m.load(5, InstructionAdapter.OBJECT_TYPE);
m.invokevirtual(this.className, singleMethod, SINGLE_DESC, false);
m.astore(Type.DOUBLE_TYPE);
});
}
public void genPostprocessingMethod(String name, Consumer<InstructionAdapter> generator) {
if (!this.postProcessMethods.contains(name)) {
InstructionAdapter adapter = new InstructionAdapter(new AnalyzerAdapter(this.className, 18, name, "()V", this.classWriter.visitMethod(18, name, "()V", (String)null, (String[])null)));
Label start = new Label();
Label end = new Label();
adapter.visitLabel(start);
generator.accept(adapter);
adapter.visitLabel(end);
adapter.visitMaxs(0, 0);
adapter.visitLocalVariable("this", this.classDesc, (String)null, start, end, 0);
this.postProcessMethods.add(name);
}
}
static {
SINGLE_DESC = Type.getMethodDescriptor(Type.getType(Double.TYPE), new Type[]{Type.getType(Integer.TYPE), Type.getType(Integer.TYPE), Type.getType(Integer.TYPE), Type.getType(EvalType.class)});
MULTI_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[]{Type.getType(double[].class), Type.getType(int[].class), Type.getType(int[].class), Type.getType(int[].class), Type.getType(EvalType.class), Type.getType(ArrayCache.class)});
}
public interface LocalVarConsumer {
int createLocalVariable(String var1, String var2);
}
private static record FieldRecord(String name, int ordinal, Class<?> type) {
private FieldRecord(String name, int ordinal, Class<?> type) {
this.name = name;
this.ordinal = ordinal;
this.type = type;
}
public String name() {
return this.name;
}
public int ordinal() {
return this.ordinal;
}
public Class<?> type() {
return this.type;
}
}
}
@FunctionalInterface
public interface EvalMultiInterface {
void evalMulti(double[] var1, int[] var2, int[] var3, int[] var4, EvalType var5);
}
@FunctionalInterface
public interface EvalSingleInterface {
double evalSingle(int var1, int var2, int var3, EvalType var4);
}
}

View File

@@ -0,0 +1,98 @@
package com.ishland.c2me.opts.dfc.common.gen;
import com.google.common.base.Suppliers;
import com.ishland.c2me.opts.dfc.common.ducks.IBlendingAwareVisitor;
import com.ishland.c2me.opts.dfc.common.ducks.IFastCacheLike;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.function.Supplier;
import net.minecraft.world.level.levelgen.DensityFunction;
public class CompiledDensityFunction extends SubCompiledDensityFunction {
private final CompiledEntry compiledEntry;
public CompiledDensityFunction(CompiledEntry compiledEntry, DensityFunction blendingFallback) {
super(compiledEntry, compiledEntry, blendingFallback);
this.compiledEntry = (CompiledEntry)Objects.requireNonNull(compiledEntry);
}
private CompiledDensityFunction(CompiledEntry compiledEntry, Supplier<DensityFunction> blendingFallback) {
super(compiledEntry, compiledEntry, blendingFallback);
this.compiledEntry = (CompiledEntry)Objects.requireNonNull(compiledEntry);
}
public DensityFunction mapAll(Visitor visitor) {
if (visitor instanceof IBlendingAwareVisitor blendingAwareVisitor) {
if (blendingAwareVisitor.c2me$isBlendingEnabled()) {
DensityFunction fallback1 = this.getFallback();
if (fallback1 == null) {
throw new IllegalStateException("blendingFallback is no more");
}
return fallback1.mapAll(visitor);
}
}
boolean modified = false;
List<Object> args = this.compiledEntry.getArgs();
ListIterator<Object> iterator = args.listIterator();
Object next;
while(iterator.hasNext()) {
next = iterator.next();
if (next instanceof DensityFunction df) {
if (!(df instanceof IFastCacheLike)) {
DensityFunction applied = df.mapAll(visitor);
if (df != applied) {
iterator.set(applied);
modified = true;
}
}
}
if (next instanceof NoiseHolder noise) {
NoiseHolder applied = visitor.visitNoise(noise);
if (noise != applied) {
iterator.set(applied);
modified = true;
}
}
}
iterator = args.listIterator();
while(iterator.hasNext()) {
next = iterator.next();
if (next instanceof IFastCacheLike cacheLike) {
DensityFunction applied = visitor.apply(cacheLike);
if (applied == cacheLike.c2me$getDelegate()) {
iterator.set((Object)null);
modified = true;
} else {
if (!(applied instanceof IFastCacheLike)) {
throw new UnsupportedOperationException("Unsupported transformation on Wrapping node");
}
IFastCacheLike newCacheLike = (IFastCacheLike)applied;
iterator.set(newCacheLike);
modified = true;
}
}
}
Supplier<DensityFunction> fallback = this.blendingFallback != null ? Suppliers.memoize(() -> {
DensityFunction densityFunction = (DensityFunction)this.blendingFallback.get();
return densityFunction != null ? densityFunction.mapAll(visitor) : null;
}) : null;
if (fallback != this.blendingFallback) {
modified = true;
}
if (modified) {
return new CompiledDensityFunction(this.compiledEntry.newInstance(args), fallback);
} else {
return this;
}
}
}

View File

@@ -0,0 +1,15 @@
package com.ishland.c2me.opts.dfc.common.gen;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.util.ArrayCache;
import java.util.List;
public interface CompiledEntry extends ISingleMethod, IMultiMethod {
double evalSingle(int var1, int var2, int var3, EvalType var4);
void evalMulti(double[] var1, int[] var2, int[] var3, int[] var4, EvalType var5, ArrayCache var6);
CompiledEntry newInstance(List<?> var1);
List<Object> getArgs();
}

View File

@@ -0,0 +1,28 @@
package com.ishland.c2me.opts.dfc.common.gen;
import com.ishland.c2me.opts.dfc.common.ducks.IBlendingAwareVisitor;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
import org.jetbrains.annotations.NotNull;
public class DelegatingBlendingAwareVisitor implements IBlendingAwareVisitor, DensityFunction.Visitor {
private final DensityFunction.Visitor delegate;
private final boolean blendingEnabled;
public DelegatingBlendingAwareVisitor(DensityFunction.Visitor delegate, boolean blendingEnabled) {
this.delegate = Objects.requireNonNull(delegate);
this.blendingEnabled = blendingEnabled;
}
public @NotNull DensityFunction apply(@NotNull DensityFunction densityFunction) {
return this.delegate.apply(densityFunction);
}
public DensityFunction.@NotNull NoiseHolder visitNoise(DensityFunction.@NotNull NoiseHolder noiseDensityFunction) {
return this.delegate.visitNoise(noiseDensityFunction);
}
public boolean c2me$isBlendingEnabled() {
return this.blendingEnabled;
}
}

View File

@@ -0,0 +1,9 @@
package com.ishland.c2me.opts.dfc.common.gen;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.util.ArrayCache;
@FunctionalInterface
public interface IMultiMethod {
void evalMulti(double[] var1, int[] var2, int[] var3, int[] var4, EvalType var5, ArrayCache var6);
}

View File

@@ -0,0 +1,8 @@
package com.ishland.c2me.opts.dfc.common.gen;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
@FunctionalInterface
public interface ISingleMethod {
double evalSingle(int var1, int var2, int var3, EvalType var4);
}

View File

@@ -0,0 +1,142 @@
package com.ishland.c2me.opts.dfc.common.gen;
import com.google.common.base.Suppliers;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.ducks.IArrayCacheCapable;
import com.ishland.c2me.opts.dfc.common.ducks.IBlendingAwareVisitor;
import com.ishland.c2me.opts.dfc.common.ducks.ICoordinatesFilling;
import com.ishland.c2me.opts.dfc.common.util.ArrayCache;
import com.ishland.c2me.opts.dfc.common.vif.EachApplierVanillaInterface;
import java.util.Objects;
import java.util.function.Supplier;
import net.minecraft.util.KeyDispatchDataCodec;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.NoiseChunk;
import net.minecraft.world.level.levelgen.blending.Blender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SubCompiledDensityFunction implements DensityFunction {
private static final Logger LOGGER = LoggerFactory.getLogger(SubCompiledDensityFunction.class);
private final ISingleMethod singleMethod;
private final IMultiMethod multiMethod;
protected final Supplier<DensityFunction> blendingFallback;
public SubCompiledDensityFunction(ISingleMethod singleMethod, IMultiMethod multiMethod, DensityFunction blendingFallback) {
this(singleMethod, multiMethod, unwrap(blendingFallback));
}
protected SubCompiledDensityFunction(ISingleMethod singleMethod, IMultiMethod multiMethod, Supplier<DensityFunction> blendingFallback) {
this.singleMethod = (ISingleMethod)Objects.requireNonNull(singleMethod);
this.multiMethod = (IMultiMethod)Objects.requireNonNull(multiMethod);
this.blendingFallback = blendingFallback;
}
private static Supplier<DensityFunction> unwrap(DensityFunction densityFunction) {
if (densityFunction instanceof SubCompiledDensityFunction scdf) {
return scdf.blendingFallback;
} else {
return densityFunction != null ? Suppliers.ofInstance(densityFunction) : null;
}
}
public double compute(FunctionContext pos) {
if (pos.getBlender() != Blender.empty()) {
DensityFunction fallback = this.getFallback();
if (fallback == null) {
throw new IllegalStateException("blendingFallback is no more");
} else {
return fallback.compute(pos);
}
} else {
return this.singleMethod.evalSingle(pos.blockX(), pos.blockY(), pos.blockZ(), EvalType.from(pos));
}
}
public void fillArray(double[] densities, ContextProvider applier) {
if (applier instanceof NoiseChunk sampler) {
if (sampler.getBlender() != Blender.empty()) {
DensityFunction fallback = this.getFallback();
if (fallback == null) {
throw new IllegalStateException("blendingFallback is no more");
}
fallback.fillArray(densities, applier);
return;
}
}
if (applier instanceof EachApplierVanillaInterface vanillaInterface) {
this.multiMethod.evalMulti(densities, vanillaInterface.getX(), vanillaInterface.getY(), vanillaInterface.getZ(), EvalType.from(applier), vanillaInterface.c2me$getArrayCache());
} else {
ArrayCache var10000;
if (applier instanceof IArrayCacheCapable cacheCapable) {
var10000 = cacheCapable.c2me$getArrayCache();
} else {
var10000 = new ArrayCache();
}
ArrayCache cache = var10000;
int[] x = cache.getIntArray(densities.length, false);
int[] y = cache.getIntArray(densities.length, false);
int[] z = cache.getIntArray(densities.length, false);
if (applier instanceof ICoordinatesFilling coordinatesFilling) {
coordinatesFilling.c2me$fillCoordinates(x, y, z);
} else {
for(int i = 0; i < densities.length; ++i) {
FunctionContext pos = applier.forIndex(i);
x[i] = pos.blockX();
y[i] = pos.blockY();
z[i] = pos.blockZ();
}
}
this.multiMethod.evalMulti(densities, x, y, z, EvalType.from(applier), cache);
}
}
public DensityFunction mapAll(Visitor visitor) {
if (this.getClass() != SubCompiledDensityFunction.class) {
throw new AbstractMethodError();
} else {
if (visitor instanceof IBlendingAwareVisitor) {
IBlendingAwareVisitor blendingAwareVisitor = (IBlendingAwareVisitor)visitor;
if (blendingAwareVisitor.c2me$isBlendingEnabled()) {
DensityFunction fallback1 = this.getFallback();
if (fallback1 == null) {
throw new IllegalStateException("blendingFallback is no more");
}
return fallback1.mapAll(visitor);
}
}
boolean modified = false;
Supplier<DensityFunction> fallback = this.blendingFallback != null ? Suppliers.memoize(() -> {
DensityFunction densityFunction = (DensityFunction)this.blendingFallback.get();
return densityFunction != null ? densityFunction.mapAll(visitor) : null;
}) : null;
if (fallback != this.blendingFallback) {
modified = true;
}
return modified ? new SubCompiledDensityFunction(this.singleMethod, this.multiMethod, fallback) : this;
}
}
public double minValue() {
return Double.MIN_VALUE;
}
public double maxValue() {
return Double.MAX_VALUE;
}
public KeyDispatchDataCodec<? extends DensityFunction> codec() {
throw new UnsupportedOperationException();
}
protected DensityFunction getFallback() {
return this.blendingFallback != null ? (DensityFunction)this.blendingFallback.get() : null;
}
}

View File

@@ -0,0 +1,57 @@
package com.ishland.c2me.opts.dfc.common.util;
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
import java.util.Arrays;
public class ArrayCache {
private final Int2ReferenceArrayMap<ReferenceArrayList<double[]>> doubleArrayCache = new Int2ReferenceArrayMap<>();
private final Int2ReferenceArrayMap<ReferenceArrayList<int[]>> intArrayCache = new Int2ReferenceArrayMap<>();
public ArrayCache() {
}
public double[] getDoubleArray(int size, boolean zero) {
ReferenceArrayList<double[]> list = this.doubleArrayCache.computeIfAbsent(size, (k) -> {
return new ReferenceArrayList<>();
});
if (list.isEmpty()) {
return new double[size];
} else {
double[] popped = list.pop();
if (zero) {
Arrays.fill(popped, 0.0);
}
return popped;
}
}
public int[] getIntArray(int size, boolean zero) {
ReferenceArrayList<int[]> list = this.intArrayCache.computeIfAbsent(size, (k) -> {
return new ReferenceArrayList<>();
});
if (list.isEmpty()) {
return new int[size];
} else {
int[] popped = list.pop();
if (zero) {
Arrays.fill(popped, 0);
}
return popped;
}
}
public void recycle(double[] array) {
this.doubleArrayCache.computeIfAbsent(array.length, (k) -> {
return new ReferenceArrayList<>();
}).add(array);
}
public void recycle(int[] array) {
this.intArrayCache.computeIfAbsent(array.length, (k) -> {
return new ReferenceArrayList<>();
}).add(array);
}
}

View File

@@ -0,0 +1,98 @@
package com.ishland.c2me.opts.dfc.common.vif;
import com.ishland.c2me.opts.dfc.common.ast.AstNode;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.ast.misc.CacheLikeNode;
import com.ishland.c2me.opts.dfc.common.ast.misc.DelegateNode;
import com.ishland.c2me.opts.dfc.common.ducks.IFastCacheLike;
import java.util.Objects;
import net.minecraft.util.KeyDispatchDataCodec;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.NoiseChunk;
import net.minecraft.world.level.levelgen.blending.Blender;
public class AstVanillaInterface implements DensityFunction {
private final AstNode astNode;
private final DensityFunction blendingFallback;
public AstVanillaInterface(AstNode astNode, DensityFunction blendingFallback) {
this.astNode = (AstNode)Objects.requireNonNull(astNode);
this.blendingFallback = blendingFallback;
}
public double compute(FunctionContext pos) {
if (pos.getBlender() != Blender.empty()) {
if (this.blendingFallback == null) {
throw new IllegalStateException("blendingFallback is no more");
} else {
return this.blendingFallback.compute(pos);
}
} else {
return this.astNode.evalSingle(pos.blockX(), pos.blockY(), pos.blockZ(), EvalType.from(pos));
}
}
public void fillArray(double[] densities, ContextProvider applier) {
if (applier instanceof NoiseChunk sampler) {
if (sampler.getBlender() != Blender.empty()) {
if (this.blendingFallback == null) {
throw new IllegalStateException("blendingFallback is no more");
}
this.blendingFallback.fillArray(densities, applier);
return;
}
}
if (applier instanceof EachApplierVanillaInterface vanillaInterface) {
this.astNode.evalMulti(densities, vanillaInterface.getX(), vanillaInterface.getY(), vanillaInterface.getZ(), EvalType.from(applier));
} else {
int[] x = new int[densities.length];
int[] y = new int[densities.length];
int[] z = new int[densities.length];
for(int i = 0; i < densities.length; ++i) {
FunctionContext pos = applier.forIndex(i);
x[i] = pos.blockX();
y[i] = pos.blockY();
z[i] = pos.blockZ();
}
this.astNode.evalMulti(densities, x, y, z, EvalType.from(applier));
}
}
public DensityFunction mapAll(Visitor visitor) {
AstNode transformed = this.astNode.transform((astNode) -> {
if (astNode instanceof DelegateNode delegateNode) {
return new DelegateNode(delegateNode.getDelegate().mapAll(visitor));
} else if (astNode instanceof CacheLikeNode cacheLikeNode) {
return new CacheLikeNode((IFastCacheLike)cacheLikeNode.getCacheLike().mapAll(visitor), cacheLikeNode.getDelegate());
} else {
return astNode;
}
});
DensityFunction blendingFallback1 = this.blendingFallback != null ? this.blendingFallback.mapAll(visitor) : null;
return transformed == this.astNode && blendingFallback1 == this.blendingFallback ? this : new AstVanillaInterface(transformed, blendingFallback1);
}
public double minValue() {
return this.blendingFallback.minValue();
}
public double maxValue() {
return this.blendingFallback.maxValue();
}
public KeyDispatchDataCodec<? extends DensityFunction> codec() {
throw new UnsupportedOperationException();
}
public AstNode getAstNode() {
return this.astNode;
}
public DensityFunction getBlendingFallback() {
return this.blendingFallback;
}
}

View File

@@ -0,0 +1,58 @@
package com.ishland.c2me.opts.dfc.common.vif;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import com.ishland.c2me.opts.dfc.common.ducks.IArrayCacheCapable;
import com.ishland.c2me.opts.dfc.common.util.ArrayCache;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
public class EachApplierVanillaInterface implements DensityFunction.ContextProvider, IArrayCacheCapable {
private final int[] x;
private final int[] y;
private final int[] z;
private final EvalType type;
private final ArrayCache cache;
public EachApplierVanillaInterface(int[] x, int[] y, int[] z, EvalType type) {
this(x, y, z, type, new ArrayCache());
}
public EachApplierVanillaInterface(int[] x, int[] y, int[] z, EvalType type, ArrayCache cache) {
this.x = (int[])Objects.requireNonNull(x);
this.y = (int[])Objects.requireNonNull(y);
this.z = (int[])Objects.requireNonNull(z);
this.type = (EvalType)Objects.requireNonNull(type);
this.cache = (ArrayCache)Objects.requireNonNull(cache);
}
public DensityFunction.FunctionContext forIndex(int index) {
return new NoisePosVanillaInterface(this.x[index], this.y[index], this.z[index], this.type);
}
public void fillAllDirectly(double[] densities, DensityFunction densityFunction) {
for(int i = 0; i < this.x.length; ++i) {
densities[i] = densityFunction.compute(this.forIndex(i));
}
}
public int[] getX() {
return this.x;
}
public int[] getY() {
return this.y;
}
public int[] getZ() {
return this.z;
}
public EvalType getType() {
return this.type;
}
public ArrayCache c2me$getArrayCache() {
return this.cache;
}
}

View File

@@ -0,0 +1,35 @@
package com.ishland.c2me.opts.dfc.common.vif;
import com.ishland.c2me.opts.dfc.common.ast.EvalType;
import java.util.Objects;
import net.minecraft.world.level.levelgen.DensityFunction;
public class NoisePosVanillaInterface implements DensityFunction.FunctionContext {
private final int x;
private final int y;
private final int z;
private final EvalType type;
public NoisePosVanillaInterface(int x, int y, int z, EvalType type) {
this.x = x;
this.y = y;
this.z = z;
this.type = (EvalType)Objects.requireNonNull(type);
}
public int blockX() {
return this.x;
}
public int blockY() {
return this.y;
}
public int blockZ() {
return this.z;
}
public EvalType getType() {
return this.type;
}
}

View File

@@ -0,0 +1,35 @@
package com.ishland.c2me.opts.dfc.util;
import java.io.File;
import java.io.IOException;
public final class Files {
public static void deleteRecursively(File dir) throws IOException {
if (dir == null || !dir.isDirectory()) {
return;
}
try {
File[] files = dir.listFiles();
if (files == null) {
throw new IOException("Error enumerating directory during recursive delete operation: " + dir.getAbsolutePath());
}
for (File child : files) {
if (child.isDirectory()) {
Files.deleteRecursively(child);
} else if (child.isFile()) {
if (!child.delete()) {
throw new IOException("Error deleting file during recursive delete operation: " + child.getAbsolutePath());
}
}
}
if (!dir.delete()) {
throw new IOException("Error deleting directory during recursive delete operation: " + dir.getAbsolutePath());
}
} catch (SecurityException ex) {
throw new IOException("Security error during recursive delete operation", ex);
}
}
}

View File

@@ -0,0 +1,42 @@
package com.ishland.c2me.opts.worldgen.general.common.random_instances;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.PositionalRandomFactory;
import net.minecraft.world.level.levelgen.SingleThreadedRandomSource;
import net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus;
import net.minecraft.world.level.levelgen.XoroshiroRandomSource;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
public class RandomUtils {
private static final ThreadLocal<XoroshiroRandomSource> xoroshiro = ThreadLocal.withInitial(() -> new XoroshiroRandomSource(0L, 0L));
private static final ThreadLocal<SingleThreadedRandomSource> simple = ThreadLocal.withInitial(() -> new SingleThreadedRandomSource(0L));
public static void derive(PositionalRandomFactory deriver, RandomSource random, int x, int y, int z) {
if (deriver instanceof XoroshiroRandomSource.XoroshiroPositionalRandomFactory(long seedLo, long seedHi)) {
final Xoroshiro128PlusPlus implementation = ((XoroshiroRandomSource) random).randomNumberGenerator;
implementation.seedLo = (Mth.getSeed(x, y, z) ^ seedLo);
implementation.seedHi = (seedHi);
return;
}
if (deriver instanceof LegacyRandomSource.LegacyPositionalRandomFactory(long seed)) {
final SingleThreadedRandomSource random1 = (SingleThreadedRandomSource) random;
random1.setSeed(Mth.getSeed(x, y, z) ^ seed);
return;
}
throw new IllegalArgumentException();
}
@Contract("null -> fail")
public static @NotNull RandomSource getRandom(PositionalRandomFactory deriver) {
if (deriver instanceof XoroshiroRandomSource.XoroshiroPositionalRandomFactory) {
return new XoroshiroRandomSource(0L, 0L);
}
if (deriver instanceof LegacyRandomSource.LegacyPositionalRandomFactory) {
return new SingleThreadedRandomSource(0L);
}
throw new IllegalArgumentException();
}
}

View File

@@ -0,0 +1,27 @@
package com.ishland.flowsched.util;
public final class Assertions {
public static void assertTrue(boolean value, String message) {
if (!value) {
final AssertionError error = new AssertionError(message);
error.printStackTrace();
throw error;
}
}
public static void assertTrue(boolean state, String format, Object... args) {
if (!state) {
final AssertionError error = new AssertionError(String.format(format, args));
error.printStackTrace();
throw error;
}
}
public static void assertTrue(boolean value) {
if (!value) {
final AssertionError error = new AssertionError();
error.printStackTrace();
throw error;
}
}
}