9
0
mirror of https://github.com/BX-Team/DivineMC.git synced 2025-12-19 14:59:25 +00:00
Files
DivineMC/patches/removed/1.21.4/server/0031-Density-Function-Compiler.patch
2025-03-13 22:36:44 +03:00

1206 lines
58 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
Date: Wed, 12 Feb 2025 01:05:50 +0300
Subject: [PATCH] Density Function Compiler
Implements density function compiler to accelerate world generation from C2ME
Density function: https://minecraft.wiki/w/Density_function
This functionality compiles density functions from world generation
datapacks (including vanilla generation) to JVM bytecode to increase
performance by allowing JVM JIT to better optimize the code.
All functions provided by vanilla are implemented.
Not all server will benefit performance from this feature, as it
can sometimes slow down chunk performance than speed it up
diff --git a/net/minecraft/util/CubicSpline.java b/net/minecraft/util/CubicSpline.java
index f36f8f2d49d4eba5c80eb243883749d6f831eb8a..b43b7e242ea0a4f87704853c03201144ce355565 100644
--- a/net/minecraft/util/CubicSpline.java
+++ b/net/minecraft/util/CubicSpline.java
@@ -254,31 +254,47 @@ public interface CubicSpline<C, I extends ToFloatFunction<C>> extends ToFloatFun
@Override
public float apply(C object) {
- float f = this.coordinate.apply(object);
- int i = findIntervalStart(this.locations, f);
- int i1 = this.locations.length - 1;
- if (i < 0) {
- return linearExtend(f, this.locations, this.values.get(0).apply(object), this.derivatives, 0);
- } else if (i == i1) {
- return linearExtend(f, this.locations, this.values.get(i1).apply(object), this.derivatives, i1);
+ // DivineMC start - Density Function Compiler
+ float point = this.coordinate.apply(object);
+ int rangeForLocation = findIntervalStart(this.locations, point);
+ int last = this.locations.length - 1;
+ if (rangeForLocation < 0) {
+ return linearExtend(point, this.locations, this.values.get(0).apply(object), this.derivatives, 0);
+ } else if (rangeForLocation == last) {
+ return linearExtend(point, this.locations, this.values.get(last).apply(object), this.derivatives, last);
} else {
- float f1 = this.locations[i];
- float f2 = this.locations[i + 1];
- float f3 = (f - f1) / (f2 - f1);
- ToFloatFunction<C> toFloatFunction = (ToFloatFunction<C>)this.values.get(i);
- ToFloatFunction<C> toFloatFunction1 = (ToFloatFunction<C>)this.values.get(i + 1);
- float f4 = this.derivatives[i];
- float f5 = this.derivatives[i + 1];
- float f6 = toFloatFunction.apply(object);
- float f7 = toFloatFunction1.apply(object);
- float f8 = f4 * (f2 - f1) - (f7 - f6);
- float f9 = -f5 * (f2 - f1) + (f7 - f6);
- return Mth.lerp(f3, f6, f7) + f3 * (1.0F - f3) * Mth.lerp(f3, f8, f9);
+ float loc0 = this.locations[rangeForLocation];
+ float loc1 = this.locations[rangeForLocation + 1];
+ float locDist = loc1 - loc0;
+ float k = (point - loc0) / locDist;
+ float n = this.values.get(rangeForLocation).apply(object);
+ float o = this.values.get(rangeForLocation + 1).apply(object);
+ float onDist = o - n;
+ float p = this.derivatives[rangeForLocation] * locDist - onDist;
+ float q = -this.derivatives[rangeForLocation + 1] * locDist + onDist;
+ return Mth.lerp(k, n, o) + k * (1.0F - k) * Mth.lerp(k, p, q);
}
+ // DivineMC end - Density Function Compiler
}
private static int findIntervalStart(float[] locations, float start) {
- return Mth.binarySearch(0, locations.length, i -> start < locations[i]) - 1;
+ // DivineMC start - Density Function Compiler
+ int min = 0;
+ int i = locations.length;
+
+ while (i > 0) {
+ int j = i / 2;
+ int k = min + j;
+ if (start < locations[k]) {
+ i = j;
+ } else {
+ min = k + 1;
+ i -= j + 1;
+ }
+ }
+
+ return min - 1;
+ // DivineMC end - Density Function Compiler
}
@VisibleForTesting
@@ -313,5 +329,27 @@ public interface CubicSpline<C, I extends ToFloatFunction<C>> extends ToFloatFun
this.derivatives
);
}
+
+ // DivineMC start - Density Function Compiler
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Multipoint<?, ?> that = (Multipoint<?, ?>) o;
+ return java.util.Objects.equals(coordinate, that.coordinate()) && java.util.Arrays.equals(locations, that.locations()) && java.util.Objects.equals(values, that.values()) && java.util.Arrays.equals(derivatives, that.derivatives());
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+
+ result = 31 * result + java.util.Objects.hashCode(coordinate);
+ result = 31 * result + java.util.Arrays.hashCode(locations);
+ result = 31 * result + java.util.Objects.hashCode(values);
+ result = 31 * result + java.util.Arrays.hashCode(derivatives);
+
+ return result;
+ }
+ // DivineMC end - Density Function Compiler
}
}
diff --git a/net/minecraft/world/level/levelgen/DensityFunctions.java b/net/minecraft/world/level/levelgen/DensityFunctions.java
index 7178013421233d7dab36eb07a768907ce40e8745..f56321eefa5fcdfdb30883beaf97c87ac6fa0183 100644
--- a/net/minecraft/world/level/levelgen/DensityFunctions.java
+++ b/net/minecraft/world/level/levelgen/DensityFunctions.java
@@ -275,38 +275,66 @@ public final class DensityFunctions {
@Override
public void fillArray(double[] array, DensityFunction.ContextProvider contextProvider) {
- this.argument1.fillArray(array, contextProvider);
- switch (this.type) {
- case ADD:
- double[] doubles = new double[array.length];
- this.argument2.fillArray(doubles, contextProvider);
-
- for (int i = 0; i < array.length; i++) {
- array[i] += doubles[i];
- }
- break;
- case MUL:
- for (int i1 = 0; i1 < array.length; i1++) {
- double d = array[i1];
- array[i1] = d == 0.0 ? 0.0 : d * this.argument2.compute(contextProvider.forIndex(i1));
- }
- break;
- case MIN:
- double d1 = this.argument2.minValue();
+ // DivineMC start - Density Function Compiler
+ Runnable run = () -> {
+ this.argument1.fillArray(array, contextProvider);
+ switch (this.type) {
+ case ADD:
+ double[] doubles = new double[array.length];
+ this.argument2.fillArray(doubles, contextProvider);
+
+ for (int i = 0; i < array.length; i++) {
+ array[i] += doubles[i];
+ }
+ break;
+ case MUL:
+ for (int i1 = 0; i1 < array.length; i1++) {
+ double d = array[i1];
+ array[i1] = d == 0.0 ? 0.0 : d * this.argument2.compute(contextProvider.forIndex(i1));
+ }
+ break;
+ case MIN:
+ double d1 = this.argument2.minValue();
+
+ for (int i2 = 0; i2 < array.length; i2++) {
+ double d2 = array[i2];
+ array[i2] = d2 < d1 ? d2 : Math.min(d2, this.argument2.compute(contextProvider.forIndex(i2)));
+ }
+ break;
+ case MAX:
+ d1 = this.argument2.maxValue();
+
+ for (int i2 = 0; i2 < array.length; i2++) {
+ double d2 = array[i2];
+ array[i2] = d2 > d1 ? d2 : Math.max(d2, this.argument2.compute(contextProvider.forIndex(i2)));
+ }
+ }
+ };
+ if (org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler && this.type == DensityFunctions.TwoArgumentSimpleFunction.Type.ADD) {
+ this.argument1.fillArray(array, contextProvider);
+ double[] ds;
- for (int i2 = 0; i2 < array.length; i2++) {
- double d2 = array[i2];
- array[i2] = d2 < d1 ? d2 : Math.min(d2, this.argument2.compute(contextProvider.forIndex(i2)));
- }
- break;
- case MAX:
- d1 = this.argument2.maxValue();
+ org.bxteam.divinemc.dfc.common.util.ArrayCache arrayCache = contextProvider instanceof org.bxteam.divinemc.dfc.common.ducks.IArrayCacheCapable arrayCacheCapable ? arrayCacheCapable.c2me$getArrayCache() : null;
- for (int i2 = 0; i2 < array.length; i2++) {
- double d2 = array[i2];
- array[i2] = d2 > d1 ? d2 : Math.max(d2, this.argument2.compute(contextProvider.forIndex(i2)));
- }
+ if (arrayCache != null) {
+ ds = arrayCache.getDoubleArray(array.length, false);
+ } else {
+ ds = new double[array.length];
+ }
+
+ this.argument2.fillArray(ds, contextProvider);
+
+ for (int i = 0; i < array.length; i++) {
+ array[i] += ds[i];
+ }
+
+ if (arrayCache != null) {
+ arrayCache.recycle(ds);
+ }
+ } else {
+ run.run();
}
+ // DivineMC end - Density Function Compiler
}
@Override
@@ -704,7 +732,105 @@ public final class DensityFunctions {
}
}
- protected record Marker(@Override DensityFunctions.Marker.Type type, @Override DensityFunction wrapped) implements DensityFunctions.MarkerOrMarked {
+ // DivineMC start - Density Function Compiler
+ public static final class Marker implements org.bxteam.divinemc.dfc.common.ducks.IFastCacheLike, org.bxteam.divinemc.dfc.common.ducks.IEqualityOverriding, MarkerOrMarked {
+ private final Type type;
+ private final DensityFunction wrapped;
+ private Object c2me$optionalEquality;
+
+ @Override
+ public boolean equals(final Object that) {
+ Function<Object, Boolean> original = (o) -> {
+ if (o == this) return true;
+ if (o == null || o.getClass() != this.getClass()) return false;
+ var a = (Marker) o;
+ return java.util.Objects.equals(this.type, a.type) &&
+ java.util.Objects.equals(this.wrapped, a.wrapped);
+ };
+ if (true) {
+ return original.apply(that);
+ }
+ Object a = this.c2me$getOverriddenEquality();
+ Object b = that instanceof org.bxteam.divinemc.dfc.common.ducks.IEqualityOverriding equalityOverriding ? equalityOverriding.c2me$getOverriddenEquality() : null;
+ if (a == null) {
+ return original.apply(b != null ? b : that);
+ } else {
+ return a.equals(b != null ? b : that);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ java.util.function.Supplier<Integer> original = () -> java.util.Objects.hash(type, wrapped);
+ Object c2me$optionalEquality1 = this.c2me$optionalEquality;
+ if (c2me$optionalEquality1 != null && false) {
+ return c2me$optionalEquality1.hashCode();
+ } else {
+ return original.get();
+ }
+ }
+
+ public Marker(Type type, DensityFunction wrapped) {
+ this.type = type;
+ this.wrapped = wrapped;
+ }
+
+ @Override
+ public double c2me$getCached(int x, int y, int z, org.bxteam.divinemc.dfc.common.ast.EvalType evalType) {
+ return Double.longBitsToDouble(CACHE_MISS_NAN_BITS);
+ }
+
+ @Override
+ public boolean c2me$getCached(double[] res, int[] x, int[] y, int[] z, org.bxteam.divinemc.dfc.common.ast.EvalType evalType) {
+ return false;
+ }
+
+ @Override
+ public void c2me$cache(int x, int y, int z, org.bxteam.divinemc.dfc.common.ast.EvalType evalType, double cached) {
+ // nop
+ }
+
+ @Override
+ public void c2me$cache(double[] res, int[] x, int[] y, int[] z, org.bxteam.divinemc.dfc.common.ast.EvalType evalType) {
+ // nop
+ }
+
+ @Override
+ public DensityFunction c2me$getDelegate() {
+ return this.wrapped;
+ }
+
+ @Override
+ public DensityFunction c2me$withDelegate(DensityFunction delegate) {
+ DensityFunctions.Marker wrapping = new DensityFunctions.Marker(this.type(), delegate);
+ ((org.bxteam.divinemc.dfc.common.ducks.IEqualityOverriding) (Object) wrapping).c2me$overrideEquality(this);
+ return wrapping;
+ }
+
+ @Override
+ public void c2me$overrideEquality(Object object) {
+ Object inner = object;
+ while (true) {
+ Object inner1 = inner instanceof org.bxteam.divinemc.dfc.common.ducks.IEqualityOverriding e1 ? e1.c2me$getOverriddenEquality() : null;
+ if (inner1 == null) {
+ this.c2me$optionalEquality = inner;
+ break;
+ }
+ inner = inner1;
+ }
+ }
+
+ @Override
+ public Object c2me$getOverriddenEquality() {
+ return this.c2me$optionalEquality;
+ }
+
+ @Override
+ public DensityFunction mapAll(Visitor visitor) {
+ return visitor.apply(this.c2me$withDelegate(this.wrapped().mapAll(visitor)));
+ }
+ // DivineMC end - Density Function Compiler
+
@Override
public double compute(DensityFunction.FunctionContext context) {
return this.wrapped.compute(context);
@@ -725,7 +851,19 @@ public final class DensityFunctions {
return this.wrapped.maxValue();
}
- static enum Type implements StringRepresentable {
+ // DivineMC start - Density Function Compiler
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public DensityFunction wrapped() {
+ return wrapped;
+ }
+
+ public static enum Type implements StringRepresentable { // - public
+ // DivineMC end - Density Function Compiler
Interpolated("interpolated"),
FlatCache("flat_cache"),
Cache2D("cache_2d"),
diff --git a/net/minecraft/world/level/levelgen/NoiseChunk.java b/net/minecraft/world/level/levelgen/NoiseChunk.java
index 977b0d595e5637c80e7d4bb20da8896a0b64b844..991025da1005d6c4122897231095dc909a11d8f7 100644
--- a/net/minecraft/world/level/levelgen/NoiseChunk.java
+++ b/net/minecraft/world/level/levelgen/NoiseChunk.java
@@ -4,9 +4,11 @@ import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.longs.Long2IntMap;
import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Supplier;
import javax.annotation.Nullable;
import net.minecraft.core.QuartPos;
import net.minecraft.core.SectionPos;
@@ -20,7 +22,18 @@ import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.levelgen.blending.Blender;
import net.minecraft.world.level.levelgen.material.MaterialRuleList;
-public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunction.FunctionContext {
+// DivineMC start - Density Function Compiler
+import org.bxteam.divinemc.dfc.common.ast.EvalType;
+import org.bxteam.divinemc.dfc.common.ducks.IArrayCacheCapable;
+import org.bxteam.divinemc.dfc.common.ducks.ICoordinatesFilling;
+import org.bxteam.divinemc.dfc.common.ducks.IFastCacheLike;
+import org.bxteam.divinemc.dfc.common.gen.DelegatingBlendingAwareVisitor;
+import org.bxteam.divinemc.dfc.common.util.ArrayCache;
+import org.bxteam.divinemc.dfc.common.vif.EachApplierVanillaInterface;
+import org.bxteam.divinemc.dfc.common.vif.NoisePosVanillaInterface;
+// DivineMC end - Density Function Compiler
+
+public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunction.FunctionContext, IArrayCacheCapable, ICoordinatesFilling {
private final NoiseSettings noiseSettings;
final int cellCountXZ;
final int cellCountY;
@@ -56,7 +69,47 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
long interpolationCounter;
long arrayInterpolationCounter;
int arrayIndex;
- private final DensityFunction.ContextProvider sliceFillingContextProvider = new DensityFunction.ContextProvider() {
+ // DivineMC start - Density Function Compiler
+ private final ArrayCache c2me$arrayCache = new ArrayCache();
+
+ @Override
+ public ArrayCache c2me$getArrayCache() {
+ return this.c2me$arrayCache != null ? this.c2me$arrayCache : new ArrayCache();
+ }
+
+ @Override
+ public void c2me$fillCoordinates(int[] x, int[] y, int[] z) {
+ int index = 0;
+ for (int i = this.cellHeight - 1; i >= 0; i--) {
+ int blockY = this.cellStartBlockY + i;
+ for (int j = 0; j < this.cellWidth; j++) {
+ int blockX = this.cellStartBlockX + j;
+ for (int k = 0; k < this.cellWidth; k++) {
+ int blockZ = this.cellStartBlockZ + k;
+
+ x[index] = blockX;
+ y[index] = blockY;
+ z[index] = blockZ;
+
+ index++;
+ }
+ }
+ }
+ }
+
+ private @org.jetbrains.annotations.NotNull DelegatingBlendingAwareVisitor c2me$getDelegatingBlendingAwareVisitor(DensityFunction.Visitor visitor) {
+ return new DelegatingBlendingAwareVisitor(visitor, this.getBlender() != Blender.empty());
+ }
+
+ private DensityFunction.Visitor modifyVisitor1(DensityFunction.Visitor visitor) {
+ return c2me$getDelegatingBlendingAwareVisitor(visitor);
+ }
+
+ private DensityFunction.Visitor modifyVisitor2(DensityFunction.Visitor visitor) {
+ return c2me$getDelegatingBlendingAwareVisitor(visitor);
+ }
+
+ public class NoiseChunkSliceFillingContextProvider implements DensityFunction.ContextProvider, IArrayCacheCapable, ICoordinatesFilling {
@Override
public DensityFunction.FunctionContext forIndex(int arrayIndex) {
NoiseChunk.this.cellStartBlockY = (arrayIndex + NoiseChunk.this.cellNoiseMinY) * NoiseChunk.this.cellHeight;
@@ -76,7 +129,23 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
values[i] = function.compute(NoiseChunk.this);
}
}
- };
+
+ @Override
+ public ArrayCache c2me$getArrayCache() {
+ return (NoiseChunk.this).c2me$getArrayCache();
+ }
+
+ @Override
+ public void c2me$fillCoordinates(int[] x, int[] y, int[] z) {
+ for (int i = 0; i < (NoiseChunk.this).cellCountY + 1; i++) {
+ x[i] = (NoiseChunk.this).cellStartBlockX + (NoiseChunk.this).inCellX;
+ y[i] = (i + (NoiseChunk.this).cellNoiseMinY) * (NoiseChunk.this).cellHeight;
+ z[i] = (NoiseChunk.this).cellStartBlockZ + (NoiseChunk.this).inCellZ;
+ }
+ }
+ }
+ private final DensityFunction.ContextProvider sliceFillingContextProvider = new NoiseChunkSliceFillingContextProvider();
+ // DivineMC end - Density Function Compiler
public static NoiseChunk forChunk(
ChunkAccess chunk,
@@ -135,7 +204,7 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
}
NoiseRouter noiseRouter = random.router();
- NoiseRouter noiseRouter1 = noiseRouter.mapAll(this::wrap);
+ NoiseRouter noiseRouter1 = noiseRouter.mapAll(org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler ? modifyVisitor1(this::wrap) : this::wrap); // DivineMC - Density Function Compiler
if (!noiseGeneratorSettings.isAquifersEnabled()) {
this.aquifer = Aquifer.createDisabled(fluidPicker);
} else {
@@ -150,7 +219,7 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
DensityFunction densityFunction = DensityFunctions.cacheAllInCell(
DensityFunctions.add(noiseRouter1.finalDensity(), DensityFunctions.BeardifierMarker.INSTANCE)
)
- .mapAll(this::wrap);
+ .mapAll(org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler ? modifyVisitor2(this::wrap) : this::wrap); // DivineMC - Density Function Compiler
list.add(context -> this.aquifer.computeSubstance(context, densityFunction.compute(context)));
if (noiseGeneratorSettings.oreVeinsEnabled()) {
list.add(OreVeinifier.create(noiseRouter1.veinToggle(), noiseRouter1.veinRidged(), noiseRouter1.veinGap(), random.oreRandom()));
@@ -162,12 +231,14 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
protected Climate.Sampler cachedClimateSampler(NoiseRouter noiseRouter, List<Climate.ParameterPoint> points) {
return new Climate.Sampler(
- noiseRouter.temperature().mapAll(this::wrap),
- noiseRouter.vegetation().mapAll(this::wrap),
- noiseRouter.continents().mapAll(this::wrap),
- noiseRouter.erosion().mapAll(this::wrap),
- noiseRouter.depth().mapAll(this::wrap),
- noiseRouter.ridges().mapAll(this::wrap),
+ // DivineMC start - Density Function Compiler
+ noiseRouter.temperature().mapAll(org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler ? modifyVisitor2(this::wrap) : this::wrap),
+ noiseRouter.vegetation().mapAll(org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler ? modifyVisitor2(this::wrap) : this::wrap),
+ noiseRouter.continents().mapAll(org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler ? modifyVisitor2(this::wrap) : this::wrap),
+ noiseRouter.erosion().mapAll(org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler ? modifyVisitor2(this::wrap) : this::wrap),
+ noiseRouter.depth().mapAll(org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler ? modifyVisitor2(this::wrap) : this::wrap),
+ noiseRouter.ridges().mapAll(org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler ? modifyVisitor2(this::wrap) : this::wrap),
+ // DivineMC end - Density Function Compiler
points
);
}
@@ -366,6 +437,13 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
}
private DensityFunction wrapNew(DensityFunction densityFunction) {
+ // DivineMC start - Density Function Compiler
+ if (org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler) {
+ if (this.interpolating && densityFunction instanceof DensityFunctions.Marker) {
+ throw new IllegalStateException("Cannot create more wrapping during interpolation loop");
+ }
+ }
+ // DivineMC end - Density Function Compiler
if (densityFunction instanceof DensityFunctions.Marker marker) {
return (DensityFunction)(switch (marker.type()) {
case Interpolated -> new NoiseChunk.NoiseInterpolator(marker.wrapped());
@@ -475,10 +553,48 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
BlockState calculate(DensityFunction.FunctionContext context);
}
- static class Cache2D implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction {
+ static class Cache2D implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction, IFastCacheLike { // DivineMC - Density Function Compiler
private DensityFunction function;
private long lastPos2D = ChunkPos.INVALID_CHUNK_POS;
private double lastValue;
+ // DivineMC start - Density Function Compiler
+ @Override
+ public double c2me$getCached(int x, int y, int z, EvalType evalType) {
+ long l = ChunkPos.asLong(x, z);
+ if (this.lastPos2D == l) {
+ return this.lastValue;
+ } else {
+ return Double.longBitsToDouble(CACHE_MISS_NAN_BITS);
+ }
+ }
+
+ @Override
+ public boolean c2me$getCached(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ return false;
+ }
+
+ @Override
+ public void c2me$cache(int x, int y, int z, EvalType evalType, double cached) {
+ this.lastPos2D = ChunkPos.asLong(x, z);
+ this.lastValue = cached;
+ }
+
+ @Override
+ public void c2me$cache(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ // nop
+ }
+
+ @Override
+ public DensityFunction c2me$getDelegate() {
+ return this.function;
+ }
+
+ @Override
+ public DensityFunction c2me$withDelegate(DensityFunction delegate) {
+ this.function = delegate;
+ return this;
+ }
+ // DivineMC end - Density Function Compiler
Cache2D(DensityFunction function) {
this.function = function;
@@ -515,9 +631,92 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
}
}
- class CacheAllInCell implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction {
- final DensityFunction noiseFiller;
+ class CacheAllInCell implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction, IFastCacheLike { // DivineMC - Density Function Compiler
+ DensityFunction noiseFiller; // DivineMC - remove final
final double[] values;
+ // DivineMC start - Density Function Compiler
+ @Override
+ public double c2me$getCached(int x, int y, int z, EvalType evalType) {
+ if (evalType == EvalType.INTERPOLATION) {
+ boolean isInInterpolationLoop = (NoiseChunk.this).interpolating;
+ if (isInInterpolationLoop) {
+ int startBlockX = (NoiseChunk.this).cellStartBlockX;
+ int startBlockY = (NoiseChunk.this).cellStartBlockY;
+ int startBlockZ = (NoiseChunk.this).cellStartBlockZ;
+ int horizontalCellBlockCount = (NoiseChunk.this).cellWidth;
+ int verticalCellBlockCount = (NoiseChunk.this).cellHeight;
+ int cellBlockX = x - startBlockX;
+ int cellBlockY = y - startBlockY;
+ int cellBlockZ = z - startBlockZ;
+ if (cellBlockX >= 0 &&
+ cellBlockY >= 0 &&
+ cellBlockZ >= 0 &&
+ cellBlockX < horizontalCellBlockCount &&
+ cellBlockY < verticalCellBlockCount &&
+ cellBlockZ < horizontalCellBlockCount) {
+ return this.values[((verticalCellBlockCount - 1 - cellBlockY) * horizontalCellBlockCount + cellBlockX)
+ * horizontalCellBlockCount
+ + cellBlockZ];
+ }
+ }
+ }
+
+ return CACHE_MISS_NAN_BITS;
+ }
+
+ @Override
+ public boolean c2me$getCached(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ if (evalType == EvalType.INTERPOLATION) {
+ boolean isInInterpolationLoop = (NoiseChunk.this).interpolating;
+ if (isInInterpolationLoop) {
+ int startBlockX = (NoiseChunk.this).cellStartBlockX;
+ int startBlockY = (NoiseChunk.this).cellStartBlockY;
+ int startBlockZ = (NoiseChunk.this).cellStartBlockZ;
+ int horizontalCellBlockCount = (NoiseChunk.this).cellWidth;
+ int verticalCellBlockCount = (NoiseChunk.this).cellHeight;
+ for (int i = 0; i < res.length; i++) {
+ int cellBlockX = x[i] - startBlockX;
+ int cellBlockY = y[i] - startBlockY;
+ int cellBlockZ = z[i] - startBlockZ;
+ if (cellBlockX >= 0 &&
+ cellBlockY >= 0 &&
+ cellBlockZ >= 0 &&
+ cellBlockX < horizontalCellBlockCount &&
+ cellBlockY < verticalCellBlockCount &&
+ cellBlockZ < horizontalCellBlockCount) {
+ res[i] = this.values[((verticalCellBlockCount - 1 - cellBlockY) * horizontalCellBlockCount + cellBlockX) * horizontalCellBlockCount + cellBlockZ];
+ } else {
+ System.out.println("partial cell cache hit");
+ return false; // partial hit possible
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void c2me$cache(int x, int y, int z, EvalType evalType, double cached) {
+ // nop
+ }
+
+ @Override
+ public void c2me$cache(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ // nop
+ }
+
+ @Override
+ public DensityFunction c2me$getDelegate() {
+ return this.noiseFiller;
+ }
+
+ @Override
+ public DensityFunction c2me$withDelegate(DensityFunction delegate) {
+ this.noiseFiller = delegate;
+ return this;
+ }
+ // DivineMC end - Density Function Compiler
CacheAllInCell(final DensityFunction noiseFilter) {
this.noiseFiller = noiseFilter;
@@ -527,18 +726,51 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
@Override
public double compute(DensityFunction.FunctionContext context) {
- if (context != NoiseChunk.this) {
- return this.noiseFiller.compute(context);
- } else if (!NoiseChunk.this.interpolating) {
- throw new IllegalStateException("Trying to sample interpolator outside the interpolation loop");
- } else {
- int i = NoiseChunk.this.inCellX;
- int i1 = NoiseChunk.this.inCellY;
- int i2 = NoiseChunk.this.inCellZ;
- return i >= 0 && i1 >= 0 && i2 >= 0 && i < NoiseChunk.this.cellWidth && i1 < NoiseChunk.this.cellHeight && i2 < NoiseChunk.this.cellWidth
- ? this.values[((NoiseChunk.this.cellHeight - 1 - i1) * NoiseChunk.this.cellWidth + i) * NoiseChunk.this.cellWidth + i2]
+ // DivineMC start - Density Function Compiler
+ Supplier<Double> run = () -> {
+ if (context != NoiseChunk.this) {
+ return this.noiseFiller.compute(context);
+ } else if (!NoiseChunk.this.interpolating) {
+ throw new IllegalStateException("Trying to sample interpolator outside the interpolation loop");
+ } else {
+ int i = NoiseChunk.this.inCellX;
+ int i1 = NoiseChunk.this.inCellY;
+ int i2 = NoiseChunk.this.inCellZ;
+ return i >= 0 && i1 >= 0 && i2 >= 0 && i < NoiseChunk.this.cellWidth && i1 < NoiseChunk.this.cellHeight && i2 < NoiseChunk.this.cellWidth
+ ? this.values[((NoiseChunk.this.cellHeight - 1 - i1) * NoiseChunk.this.cellWidth + i) * NoiseChunk.this.cellWidth + i2]
+ : this.noiseFiller.compute(context);
+ }
+ };
+ if (!org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler || context instanceof NoiseChunk) {
+ return run.get();
+ }
+ if (context instanceof NoisePosVanillaInterface vif && vif.getType() == EvalType.INTERPOLATION) {
+ boolean isInInterpolationLoop = (NoiseChunk.this).interpolating;
+ if (!isInInterpolationLoop) {
+ return run.get();
+ }
+ int startBlockX = (NoiseChunk.this).cellStartBlockX;
+ int startBlockY = (NoiseChunk.this).cellStartBlockY;
+ int startBlockZ = (NoiseChunk.this).cellStartBlockZ;
+ int horizontalCellBlockCount = (NoiseChunk.this).cellWidth;
+ int verticalCellBlockCount = (NoiseChunk.this).cellHeight;
+ int cellBlockX = context.blockX() - startBlockX;
+ int cellBlockY = context.blockY() - startBlockY;
+ int cellBlockZ = context.blockZ() - startBlockZ;
+ return cellBlockX >= 0
+ && cellBlockY >= 0
+ && cellBlockZ >= 0
+ && cellBlockX < horizontalCellBlockCount
+ && cellBlockY < verticalCellBlockCount
+ && cellBlockZ < horizontalCellBlockCount
+ ? this.values[((verticalCellBlockCount - 1 - cellBlockY) * horizontalCellBlockCount + cellBlockX)
+ * horizontalCellBlockCount
+ + cellBlockZ]
: this.noiseFiller.compute(context);
}
+
+ return run.get();
+ // DivineMC end - Density Function Compiler
}
@Override
@@ -557,13 +789,84 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
}
}
- class CacheOnce implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction {
+ class CacheOnce implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction, IFastCacheLike { // DivineMC - Density Function Compiler
private DensityFunction function;
private long lastCounter;
private long lastArrayCounter;
private double lastValue;
@Nullable
private double[] lastArray;
+ // DivineMC start - Density Function Compiler
+ private double c2me$lastValue = Double.NaN;
+ private int c2me$lastX = Integer.MIN_VALUE;
+ private int c2me$lastY = Integer.MIN_VALUE;
+ private int c2me$lastZ = Integer.MIN_VALUE;
+
+ private int[] c2me$lastXa;
+ private int[] c2me$lastYa;
+ private int[] c2me$lastZa;
+ private double[] c2me$lastValuea;
+
+ @Override
+ public double c2me$getCached(int x, int y, int z, EvalType evalType) {
+ if (c2me$lastValuea != null) {
+ for (int i = 0; i < this.c2me$lastValuea.length; i ++) {
+ if (c2me$lastXa[i] == x && c2me$lastYa[i] == y && c2me$lastZa[i] == z) {
+ return c2me$lastValuea[i];
+ }
+ }
+ }
+ if (!Double.isNaN(c2me$lastValue) && c2me$lastX == x && c2me$lastY == y && c2me$lastZ == z) {
+ return c2me$lastValue;
+ }
+
+ return Double.longBitsToDouble(CACHE_MISS_NAN_BITS);
+ }
+
+ @Override
+ public boolean c2me$getCached(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ if (c2me$lastValuea != null && Arrays.equals(y, c2me$lastYa) && Arrays.equals(x, c2me$lastXa) && Arrays.equals(z, c2me$lastZa)) {
+ System.arraycopy(c2me$lastValuea, 0, res, 0, c2me$lastValuea.length);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public void c2me$cache(int x, int y, int z, EvalType evalType, double cached) {
+ c2me$lastValue = cached;
+ c2me$lastX = x;
+ c2me$lastY = y;
+ c2me$lastZ = z;
+ }
+
+ @Override
+ public void c2me$cache(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ if (c2me$lastValuea != null && this.c2me$lastValuea.length == res.length) {
+ System.arraycopy(res, 0, this.c2me$lastValuea, 0, this.c2me$lastValuea.length);
+ System.arraycopy(x, 0, this.c2me$lastXa, 0, this.c2me$lastValuea.length);
+ System.arraycopy(y, 0, this.c2me$lastYa, 0, this.c2me$lastValuea.length);
+ System.arraycopy(z, 0, this.c2me$lastZa, 0, this.c2me$lastValuea.length);
+ } else {
+ this.c2me$lastValuea = Arrays.copyOf(res, res.length);
+ this.c2me$lastXa = Arrays.copyOf(x, x.length);
+ this.c2me$lastYa = Arrays.copyOf(y, y.length);
+ this.c2me$lastZa = Arrays.copyOf(z, z.length);
+ }
+ }
+
+ @Override
+ public DensityFunction c2me$getDelegate() {
+ return this.function;
+ }
+
+ @Override
+ public DensityFunction c2me$withDelegate(DensityFunction delegate) {
+ this.function = delegate;
+ return this;
+ }
+ // DivineMC end - Density Function Compiler
CacheOnce(final DensityFunction function) {
this.function = function;
@@ -571,34 +874,82 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
@Override
public double compute(DensityFunction.FunctionContext context) {
- if (context != NoiseChunk.this) {
- return this.function.compute(context);
- } else if (this.lastArray != null && this.lastArrayCounter == NoiseChunk.this.arrayInterpolationCounter) {
- return this.lastArray[NoiseChunk.this.arrayIndex];
- } else if (this.lastCounter == NoiseChunk.this.interpolationCounter) {
- return this.lastValue;
- } else {
- this.lastCounter = NoiseChunk.this.interpolationCounter;
- double d = this.function.compute(context);
- this.lastValue = d;
- return d;
+ // DivineMC start - Density Function Compiler
+ Supplier<Double> run = () -> {
+ if (context != NoiseChunk.this) {
+ return this.function.compute(context);
+ } else if (this.lastArray != null && this.lastArrayCounter == NoiseChunk.this.arrayInterpolationCounter) {
+ return this.lastArray[NoiseChunk.this.arrayIndex];
+ } else if (this.lastCounter == NoiseChunk.this.interpolationCounter) {
+ return this.lastValue;
+ } else {
+ this.lastCounter = NoiseChunk.this.interpolationCounter;
+ double d = this.function.compute(context);
+ this.lastValue = d;
+ return d;
+ }
+ };
+ if (!org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler || context instanceof NoiseChunk) {
+ return run.get();
}
+ int blockX = context.blockX();
+ int blockY = context.blockY();
+ int blockZ = context.blockZ();
+ if (c2me$lastValuea != null) {
+ for (int i = 0; i < this.c2me$lastValuea.length; i ++) {
+ if (c2me$lastXa[i] == blockX && c2me$lastYa[i] == blockY && c2me$lastZa[i] == blockZ) {
+ return c2me$lastValuea[i];
+ }
+ }
+ }
+ if (!Double.isNaN(c2me$lastValue) && c2me$lastX == blockX && c2me$lastY == blockY && c2me$lastZ == blockZ) {
+ return c2me$lastValue;
+ }
+ double sample = this.function.compute(context);
+ c2me$lastValue = sample;
+ c2me$lastX = blockX;
+ c2me$lastY = blockY;
+ c2me$lastZ = blockZ;
+
+ return sample;
+ // DivineMC end - Density Function Compiler
}
@Override
public void fillArray(double[] array, DensityFunction.ContextProvider contextProvider) {
- if (this.lastArray != null && this.lastArrayCounter == NoiseChunk.this.arrayInterpolationCounter) {
- System.arraycopy(this.lastArray, 0, array, 0, array.length);
- } else {
- this.wrapped().fillArray(array, contextProvider);
- if (this.lastArray != null && this.lastArray.length == array.length) {
- System.arraycopy(array, 0, this.lastArray, 0, array.length);
+ // DivineMC start - Density Function Compiler
+ Runnable run = () -> {
+ if (this.lastArray != null && this.lastArrayCounter == NoiseChunk.this.arrayInterpolationCounter) {
+ System.arraycopy(this.lastArray, 0, array, 0, array.length);
} else {
- this.lastArray = (double[])array.clone();
- }
+ this.wrapped().fillArray(array, contextProvider);
+ if (this.lastArray != null && this.lastArray.length == array.length) {
+ System.arraycopy(array, 0, this.lastArray, 0, array.length);
+ } else {
+ this.lastArray = (double[]) array.clone();
+ }
- this.lastArrayCounter = NoiseChunk.this.arrayInterpolationCounter;
+ this.lastArrayCounter = NoiseChunk.this.arrayInterpolationCounter;
+ }
+ };
+ if (!org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler || contextProvider instanceof NoiseChunk) {
+ run.run();
+ return;
+ }
+ if (contextProvider instanceof EachApplierVanillaInterface ap) {
+ if (c2me$lastValuea != null && Arrays.equals(ap.getY(), c2me$lastYa) && Arrays.equals(ap.getX(), c2me$lastXa) && Arrays.equals(ap.getZ(), c2me$lastZa)) {
+ System.arraycopy(c2me$lastValuea, 0, array, 0, c2me$lastValuea.length);
+ } else {
+ this.function.fillArray(array, contextProvider);
+ this.c2me$lastValuea = Arrays.copyOf(array, array.length);
+ this.c2me$lastXa = ap.getX();
+ this.c2me$lastYa = ap.getY();
+ this.c2me$lastZa = ap.getZ();
+ }
+ return;
}
+ this.function.fillArray(array, contextProvider);
+ // DivineMC end - Density Function Compiler
}
@Override
@@ -612,9 +963,63 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
}
}
- class FlatCache implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction {
+ class FlatCache implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction, IFastCacheLike { // DivineMC - Density Function Compiler
private DensityFunction noiseFiller;
final double[][] values;
+ // DivineMC start - Density Function Compiler
+ @Override
+ public double c2me$getCached(int x, int y, int z, EvalType evalType) {
+ int i = QuartPos.fromBlock(x);
+ int j = QuartPos.fromBlock(z);
+ int k = i - (NoiseChunk.this).firstNoiseX;
+ int l = j - (NoiseChunk.this).firstNoiseZ;
+ int m = this.values.length;
+ if (k >= 0 && l >= 0 && k < m && l < m) {
+ return this.values[k][l];
+ } else {
+ return Double.longBitsToDouble(CACHE_MISS_NAN_BITS);
+ }
+ }
+
+ @Override
+ public boolean c2me$getCached(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ for (int i = 0; i < res.length; i ++) {
+ int i1 = QuartPos.fromBlock(x[i]);
+ int j1 = QuartPos.fromBlock(z[i]);
+ int k = i1 - (NoiseChunk.this).firstNoiseX;
+ int l = j1 - (NoiseChunk.this).firstNoiseZ;
+ int m = this.values.length;
+ if (k >= 0 && l >= 0 && k < m && l < m) {
+ res[i] = this.values[k][l];
+ } else {
+ System.out.println("partial flat cache hit");
+ return false; // partial hit possible
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void c2me$cache(int x, int y, int z, EvalType evalType, double cached) {
+ // nop
+ }
+
+ @Override
+ public void c2me$cache(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ // nop
+ }
+
+ @Override
+ public DensityFunction c2me$getDelegate() {
+ return this.noiseFiller;
+ }
+
+ @Override
+ public DensityFunction c2me$withDelegate(DensityFunction delegate) {
+ this.noiseFiller = delegate;
+ return this;
+ }
+ // DivineMC end - Density Function Compiler
FlatCache(final DensityFunction noiseFiller, final boolean computeValues) {
this.noiseFiller = noiseFiller;
@@ -673,7 +1078,7 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
}
}
- public class NoiseInterpolator implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction {
+ public class NoiseInterpolator implements DensityFunctions.MarkerOrMarked, NoiseChunk.NoiseChunkDensityFunction, IFastCacheLike { // DivineMC - Density Function Compiler
double[][] slice0;
double[][] slice1;
private DensityFunction noiseFiller;
@@ -692,6 +1097,104 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
private double valueZ0;
private double valueZ1;
private double value;
+ // DivineMC start - Density Function Compiler
+ @Override
+ public double c2me$getCached(int x, int y, int z, EvalType evalType) {
+ if (evalType == EvalType.INTERPOLATION) {
+ boolean isInInterpolationLoop = (NoiseChunk.this).interpolating;
+ if (isInInterpolationLoop) {
+ if ((NoiseChunk.this).fillingCell) {
+ int startBlockX = (NoiseChunk.this).cellStartBlockX;
+ int startBlockY = (NoiseChunk.this).cellStartBlockY;
+ int startBlockZ = (NoiseChunk.this).cellStartBlockZ;
+ int horizontalCellBlockCount = (NoiseChunk.this).cellWidth;
+ int verticalCellBlockCount = (NoiseChunk.this).cellHeight;
+ int cellBlockX = x - startBlockX;
+ int cellBlockY = y - startBlockY;
+ int cellBlockZ = z - startBlockZ;
+ return Mth.lerp3(
+ (double) cellBlockX / (double) horizontalCellBlockCount,
+ (double) cellBlockY / (double) verticalCellBlockCount,
+ (double) cellBlockZ / (double) horizontalCellBlockCount,
+ this.noise000,
+ this.noise100,
+ this.noise010,
+ this.noise110,
+ this.noise001,
+ this.noise101,
+ this.noise011,
+ this.noise111
+ );
+ } else {
+ return this.value;
+ }
+ }
+ }
+
+ return CACHE_MISS_NAN_BITS;
+ }
+
+ @Override
+ public boolean c2me$getCached(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ if (evalType == EvalType.INTERPOLATION) {
+ boolean isInInterpolationLoop = (NoiseChunk.this).interpolating;
+ if (isInInterpolationLoop) {
+ if ((NoiseChunk.this).fillingCell) {
+ int startBlockX = (NoiseChunk.this).cellStartBlockX;
+ int startBlockY = (NoiseChunk.this).cellStartBlockY;
+ int startBlockZ = (NoiseChunk.this).cellStartBlockZ;
+ double horizontalCellBlockCount = (NoiseChunk.this).cellWidth;
+ double verticalCellBlockCount = (NoiseChunk.this).cellHeight;
+ for (int i = 0; i < res.length; i ++) {
+ int cellBlockX = x[i] - startBlockX;
+ int cellBlockY = y[i] - startBlockY;
+ int cellBlockZ = z[i] - startBlockZ;
+ res[i] = Mth.lerp3(
+ (double)cellBlockX / horizontalCellBlockCount,
+ (double)cellBlockY / verticalCellBlockCount,
+ (double)cellBlockZ / horizontalCellBlockCount,
+ this.noise000,
+ this.noise100,
+ this.noise010,
+ this.noise110,
+ this.noise001,
+ this.noise101,
+ this.noise011,
+ this.noise111
+ );
+ }
+ return true;
+ } else {
+ Arrays.fill(res, this.value);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void c2me$cache(int x, int y, int z, EvalType evalType, double cached) {
+ // nop
+ }
+
+ @Override
+ public void c2me$cache(double[] res, int[] x, int[] y, int[] z, EvalType evalType) {
+ // nop
+ }
+
+ @Override
+ public DensityFunction c2me$getDelegate() {
+ return this.noiseFiller;
+ }
+
+ @Override
+ public DensityFunction c2me$withDelegate(DensityFunction delegate) {
+ this.noiseFiller = delegate;
+ return this;
+ }
+ // DivineMC end - Density Function Compiler
NoiseInterpolator(final DensityFunction noiseFilter) {
this.noiseFiller = noiseFilter;
@@ -741,16 +1244,18 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
@Override
public double compute(DensityFunction.FunctionContext context) {
- if (context != NoiseChunk.this) {
- return this.noiseFiller.compute(context);
- } else if (!NoiseChunk.this.interpolating) {
- throw new IllegalStateException("Trying to sample interpolator outside the interpolation loop");
- } else {
- return NoiseChunk.this.fillingCell
- ? Mth.lerp3(
- (double)NoiseChunk.this.inCellX / NoiseChunk.this.cellWidth,
- (double)NoiseChunk.this.inCellY / NoiseChunk.this.cellHeight,
- (double)NoiseChunk.this.inCellZ / NoiseChunk.this.cellWidth,
+ // DivineMC start - Density Function Compiler
+ Supplier<Double> original = () -> {
+ if (context != NoiseChunk.this) {
+ return this.noiseFiller.compute(context);
+ } else if (!NoiseChunk.this.interpolating) {
+ throw new IllegalStateException("Trying to sample interpolator outside the interpolation loop");
+ } else {
+ return NoiseChunk.this.fillingCell
+ ? Mth.lerp3(
+ (double) NoiseChunk.this.inCellX / NoiseChunk.this.cellWidth,
+ (double) NoiseChunk.this.inCellY / NoiseChunk.this.cellHeight,
+ (double) NoiseChunk.this.inCellZ / NoiseChunk.this.cellWidth,
this.noise000,
this.noise100,
this.noise010,
@@ -760,8 +1265,45 @@ public class NoiseChunk implements DensityFunction.ContextProvider, DensityFunct
this.noise011,
this.noise111
)
- : this.value;
+ : this.value;
+ }
+ };
+ if (!org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler || context instanceof NoiseChunk) {
+ return original.get();
}
+ if (context instanceof NoisePosVanillaInterface vif && vif.getType() == EvalType.INTERPOLATION) {
+ NoiseChunk field = NoiseChunk.this;
+ boolean isInInterpolationLoop = field.interpolating;
+ boolean isSamplingForCaches = field.fillingCell;
+ if (!isInInterpolationLoop) {
+ return original.get();
+ }
+ int startBlockX = field.cellStartBlockX;
+ int startBlockY = field.cellStartBlockY;
+ int startBlockZ = field.cellStartBlockZ;
+ int horizontalCellBlockCount = field.cellWidth();
+ int verticalCellBlockCount = field.cellHeight();
+ int cellBlockX = context.blockX() - startBlockX;
+ int cellBlockY = context.blockY() - startBlockY;
+ int cellBlockZ = context.blockZ() - startBlockZ;
+ return isSamplingForCaches
+ ? Mth.lerp3(
+ (double)cellBlockX / (double)horizontalCellBlockCount,
+ (double)cellBlockY / (double)verticalCellBlockCount,
+ (double)cellBlockZ / (double)horizontalCellBlockCount,
+ this.noise000,
+ this.noise100,
+ this.noise010,
+ this.noise110,
+ this.noise001,
+ this.noise101,
+ this.noise011,
+ this.noise111
+ ) : this.value;
+ }
+
+ return original.get();
+ // DivineMC end - Density Function Compiler
}
@Override
diff --git a/net/minecraft/world/level/levelgen/RandomState.java b/net/minecraft/world/level/levelgen/RandomState.java
index f1e089ecfffa40cd794c49db30fcedf138d3fee9..4e98103b35b03cd67ab9b4bdb91c39a9c94312df 100644
--- a/net/minecraft/world/level/levelgen/RandomState.java
+++ b/net/minecraft/world/level/levelgen/RandomState.java
@@ -122,6 +122,41 @@ public final class RandomState {
this.router.ridges().mapAll(visitor),
settings.spawnTarget()
);
+
+ // DivineMC start - Density Function Compiler
+ if (org.bxteam.divinemc.DivineConfig.enableDensityFunctionCompiler) {
+ com.google.common.base.Stopwatch stopwatch = com.google.common.base.Stopwatch.createStarted();
+ it.unimi.dsi.fastutil.objects.Reference2ReferenceMap<DensityFunction, DensityFunction> tempCache = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>();
+ this.router = new NoiseRouter(
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.barrierNoise(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.fluidLevelFloodednessNoise(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.fluidLevelSpreadNoise(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.lavaNoise(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.temperature(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.vegetation(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.continents(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.erosion(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.depth(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.ridges(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.initialDensityWithoutJaggedness(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.finalDensity(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.veinToggle(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.veinRidged(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.router.veinGap(), tempCache)
+ );
+ this.sampler = new Climate.Sampler(
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.sampler.temperature(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.sampler.humidity(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.sampler.continentalness(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.sampler.erosion(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.sampler.depth(), tempCache),
+ org.bxteam.divinemc.dfc.common.gen.BytecodeGen.compile(this.sampler.weirdness(), tempCache),
+ this.sampler.spawnTarget()
+ );
+ stopwatch.stop();
+ System.out.printf("Density function compilation finished in %s%n", stopwatch);
+ }
+ // DivineMC end - Density Function Compiler
}
public NormalNoise getOrCreateNoise(ResourceKey<NormalNoise.NoiseParameters> resourceKey) {