From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JellySquid <jellysquid+atwork@protonmail.com>
Date: Fri, 23 Oct 2020 16:45:51 -0500
Subject: [PATCH] lithium NoiseChunkGeneratorMixin

Additional Optimizations By YatopiaMC,
Original code by SuperCoder79, licensed under LGPLv3
you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings)

diff --git a/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java
index 321ebe8891defb46f3ad3dfea37c9bb6e2025ad7..fa60285c0c48147ad09b9197bfe577f504dd34bd 100644
--- a/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java
+++ b/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java
@@ -5,6 +5,8 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
 import it.unimi.dsi.fastutil.objects.ObjectArrayList;
 import it.unimi.dsi.fastutil.objects.ObjectList;
 import it.unimi.dsi.fastutil.objects.ObjectListIterator;
+import org.apache.commons.math3.util.FastMath; // Yatopia Fast Math
+
 import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
@@ -111,7 +113,15 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
         return this.w == i && ((GeneratorSettingBase) this.h.get()).a(resourcekey);
     }
 
+    // Yatopia start
+    private static double sampleOctave(NoiseGeneratorPerlin sampler, double x, double y, double z, double scaledVerticalSize, double scaledY, double frequency) {
+        return sampler.sample(x, y, z, scaledVerticalSize, scaledY) / frequency;
+    }
+    // Yatopia end
+
     private double a(int i, int j, int k, double d0, double d1, double d2, double d3) {
+        // Yatopia start - replaced logic
+        /*
         double d4 = 0.0D;
         double d5 = 0.0D;
         double d6 = 0.0D;
@@ -147,7 +157,85 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
         }
 
         return MathHelper.b(d4 / 512.0D, d5 / 512.0D, (d6 / 10.0D + 1.0D) / 2.0D);
+         */
+        double frequency = 1.0;
+        double interpolationValue = 0.0;
+
+        // Calculate interpolation data to decide what noise to sample.
+        for (int octave = 0; octave < 8; octave++) {
+            double scaledVerticalScale = d3 * frequency;
+            double scaledY = j * scaledVerticalScale;
+
+            interpolationValue += sampleOctave(this.s.a(octave),
+                    NoiseGeneratorOctaves.a(i * d2 * frequency),
+                    NoiseGeneratorOctaves.a(scaledY),
+                    NoiseGeneratorOctaves.a(k * d2 * frequency), scaledVerticalScale, scaledY, frequency);
+
+            frequency /= 2.0;
+        }
+
+        double clampedInterpolation = (interpolationValue / 10.0 + 1.0) / 2.0;
+
+        if (clampedInterpolation >= 1) {
+            // Sample only upper noise, as the lower noise will be interpolated out.
+            frequency = 1.0;
+            double noise = 0.0;
+            for (int octave = 0; octave < 16; octave++) {
+                double scaledVerticalScale = d1 * frequency;
+                double scaledY = j * scaledVerticalScale;
+
+                noise += sampleOctave(this.r.a(octave),
+                        NoiseGeneratorOctaves.a(i * d0 * frequency),
+                        NoiseGeneratorOctaves.a(scaledY),
+                        NoiseGeneratorOctaves.a(k * d0 * frequency), scaledVerticalScale, scaledY, frequency);
+
+                frequency /= 2.0;
+            }
+
+            return noise / 512.0;
+        } else if (clampedInterpolation <= 0) {
+            // Sample only lower noise, as the upper noise will be interpolated out.
+            frequency = 1.0;
+            double noise = 0.0;
+            for (int octave = 0; octave < 16; octave++) {
+                double scaledVerticalScale = d1 * frequency;
+                double scaledY = j * scaledVerticalScale;
+                noise += sampleOctave(this.q.a(octave),
+                        NoiseGeneratorOctaves.a(i * d0 * frequency),
+                        NoiseGeneratorOctaves.a(scaledY),
+                        NoiseGeneratorOctaves.a(k * d0 * frequency), scaledVerticalScale, scaledY, frequency);
+
+                frequency /= 2.0;
+            }
+
+            return noise / 512.0;
+        } else {
+            // [VanillaCopy] SurfaceChunkGenerator#sampleNoise
+            // Sample both and interpolate, as in vanilla.
+
+            frequency = 1.0;
+            double lowerNoise = 0.0;
+            double upperNoise = 0.0;
+
+            for (int octave = 0; octave < 16; octave++) {
+                // Pre calculate these values to share them
+                double scaledVerticalScale = d1 * frequency;
+                double scaledY = j * scaledVerticalScale;
+                double xVal = NoiseGeneratorOctaves.a(i * d0 * frequency);
+                double yVal = NoiseGeneratorOctaves.a(scaledY);
+                double zVal = NoiseGeneratorOctaves.a(k * d0 * frequency);
+
+                upperNoise += sampleOctave(this.r.a(octave), xVal, yVal, zVal, scaledVerticalScale, scaledY, frequency);
+                lowerNoise += sampleOctave(this.q.a(octave), xVal, yVal, zVal, scaledVerticalScale, scaledY, frequency);
+
+                frequency /= 2.0;
+            }
+
+            // Vanilla behavior, return interpolated noise
+            return MathHelper.d(clampedInterpolation, lowerNoise / 512.0, upperNoise / 512.0);
+        }
     }
+    // Yatopia end
 
     private double[] b(int i, int j) {
         double[] adouble = new double[this.o + 1];
@@ -273,7 +361,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
 
         double d2 = d1 * 24.575625D - 2.0D;
 
-        return d2 < 0.0D ? d2 * 0.009486607142857142D : Math.min(d2, 1.0D) * 0.006640625D;
+        return d2 < 0.0D ? d2 * 0.009486607142857142D : FastMath.min(d2, 1.0D) * 0.006640625D; // Yatopia Fast Math
     }
 
     @Override
@@ -290,10 +378,10 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
     }
 
     private int a(int i, int j, @Nullable IBlockData[] aiblockdata, @Nullable Predicate<IBlockData> predicate) {
-        int k = Math.floorDiv(i, this.m);
-        int l = Math.floorDiv(j, this.m);
-        int i1 = Math.floorMod(i, this.m);
-        int j1 = Math.floorMod(j, this.m);
+        int k = FastMath.floorDiv(i, this.m); // Yatopia Fast Math
+        int l = FastMath.floorDiv(j, this.m); // Yatopia Fast Math
+        int i1 = FastMath.floorMod(i, this.m); // Yatopia Fast Math
+        int j1 = FastMath.floorMod(j, this.m); // Yatopia Fast Math
         double d0 = (double) i1 / (double) this.m;
         double d1 = (double) j1 / (double) this.m;
         double[][] adouble = new double[][]{this.b(k, l), this.b(k, l + 1), this.b(k + 1, l), this.b(k + 1, l + 1)};
@@ -532,9 +620,9 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
                                     StructurePiece structurepiece = (StructurePiece) objectlistiterator.next();
                                     StructureBoundingBox structureboundingbox = structurepiece.g();
 
-                                    k4 = Math.max(0, Math.max(structureboundingbox.a - j3, j3 - structureboundingbox.d));
+                                    k4 = FastMath.max(0, FastMath.max(structureboundingbox.a - j3, j3 - structureboundingbox.d)); // Yatopia Fast Math
                                     l4 = j2 - (structureboundingbox.b + (structurepiece instanceof WorldGenFeaturePillagerOutpostPoolPiece ? ((WorldGenFeaturePillagerOutpostPoolPiece) structurepiece).d() : 0));
-                                    i5 = Math.max(0, Math.max(structureboundingbox.c - i4, i4 - structureboundingbox.f));
+                                    i5 = FastMath.max(0, FastMath.max(structureboundingbox.c - i4, i4 - structureboundingbox.f)); // Yatopia Fast Math
                                 }
 
                                 objectlistiterator.back(objectlist.size());
@@ -589,7 +677,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
         double d0 = (double) (i * i + k * k);
         double d1 = (double) j + 0.5D;
         double d2 = d1 * d1;
-        double d3 = Math.pow(2.718281828459045D, -(d2 / 16.0D + d0 / 16.0D));
+        double d3 = FastMath.pow(2.718281828459045D, -(d2 / 16.0D + d0 / 16.0D)); // Yatopia Fast Math
         double d4 = -d1 * MathHelper.i(d2 / 2.0D + d0 / 2.0D) / 2.0D;
 
         return d4 * d3;
