Yatopia/patches/server/0026-lithium-MixinChunkGeneratorAbstract.patch
2020-08-06 16:02:30 -05:00

197 lines
7.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JellySquid <jellysquid+atwork@protonmail.com>
Date: Tue, 4 Aug 2020 21:06:02 +0200
Subject: [PATCH] lithium-MixinChunkGeneratorAbstract
Original code by JellySquid, licensed under GNU Lesser General Public License v3.0
you can find the original code on https://github.com/jellysquid3/lithium-fabric/tree/1.16.x/fabric (Yarn mappings)
Co-authored-by: tr7zw <tr7zw@live.de>
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/world/noise/SimplexNoiseCache.java b/src/main/java/me/jellysquid/mods/lithium/common/world/noise/SimplexNoiseCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..167498cfab7aed0deb32232082ae06a123b7a039
--- /dev/null
+++ b/src/main/java/me/jellysquid/mods/lithium/common/world/noise/SimplexNoiseCache.java
@@ -0,0 +1,133 @@
+package me.jellysquid.mods.lithium.common.world.noise;
+
+import java.util.Arrays;
+
+import it.unimi.dsi.fastutil.HashCommon;
+import net.minecraft.server.ChunkCoordIntPair;
+import net.minecraft.server.MathHelper;
+import net.minecraft.server.NoiseGenerator3Handler;
+
+/**
+ * A cache for the End's noise generator that caches computed values. Through the caching, we can eliminate a large
+ * amount of overhead in computing the noise values several hundred thousand times per chunk. This code uses the same
+ * array backed lossy cache as FastCachingLayerSampler.
+ */
+public class SimplexNoiseCache {
+ private static final int GRID_SIZE = 2;
+ private static final float MIN = -100.0F;
+ private static final float MAX = 80.0F;
+ private static final float ISLAND_RADIUS = 100.0F;
+ // The smallest encompassing power of two that can store all of the noise values in a chunk.
+ private static final int CACHE_SIZE = 8192;
+
+ private final int mask;
+ private final long[] keys;
+ private final float[] values;
+
+ private final NoiseGenerator3Handler sampler;
+
+ public SimplexNoiseCache(NoiseGenerator3Handler sampler) {
+ this.sampler = sampler;
+
+ this.mask = CACHE_SIZE - 1;
+
+ // Initialize default values
+ this.keys = new long[CACHE_SIZE];
+ Arrays.fill(this.keys, Long.MIN_VALUE);
+ this.values = new float[CACHE_SIZE];
+ }
+
+ /**
+ * Attempt to get the cached distance factor, saving computation time.
+ */
+ private float getDistanceFactor(int x, int z) {
+ // Hash key and get index
+ long key = ChunkCoordIntPair.pair(x, z);
+ int idx = (int) HashCommon.mix(key) & this.mask;
+
+ if (this.keys[idx] == key) {
+ // Cache hit, return cached value
+ return this.values[idx];
+ }
+
+ // Cache miss, compute and store value
+
+ // A marker for no value.
+ float value = -1.0F;
+
+ long lx = x;
+ long lz = z;
+ long distanceFromOriginSq = lx * lx + lz * lz;
+
+ // Ensure we are 64 grid cells away from the origin.
+ if (distanceFromOriginSq > 64 * 64) {
+ // Reduce the number of island-forming grid cells by sampling noise with a threshold
+ if (this.sampler.a(x, z) < -0.9) {
+ // Generate a pseudo-random value from 9 to 21
+ value = (Math.abs(x) * 3439.0F + Math.abs(z) * 147.0F) % 13.0F + 9.0F;
+ }
+ }
+
+ // Store values in cache
+ this.keys[idx] = key;
+ this.values[idx] = value;
+
+ return value;
+ }
+
+ /**
+ * Mapped and cleaned up implementation of the End biome source's sampler. Tries to use cached values wherever possible.
+ */
+ public float getNoiseAt(int x, int z) {
+ // [VanillaCopy] TheEndBiomeSource#getNoiseAt
+
+ int gridX = x / GRID_SIZE;
+ int gridZ = z / GRID_SIZE;
+
+ // This is the "center point", offset to center around the current grid cell
+ int gridOriginX = x % GRID_SIZE;
+ int gridOriginZ = z % GRID_SIZE;
+
+ // Initialize density for the central island
+ float density = ISLAND_RADIUS - MathHelper.sqrt(x * x + z * z) * 8.0F;
+ if (density >= MAX) {
+ return MAX;
+ }
+
+ // Iterate through 25x25 grid cells
+ for (int offsetX = -12; offsetX <= 12; ++offsetX) {
+ for (int offsetZ = -12; offsetZ <= 12; ++offsetZ) {
+ int globalGridX = gridX + offsetX;
+ int globalGridZ = gridZ + offsetZ;
+
+ // Try to retrieve values from cache
+ float distanceFactor = getDistanceFactor(globalGridX, globalGridZ);
+ if (distanceFactor != -1.0F) {
+ // Compute the distance to the origin
+ float deltaX = gridOriginX - offsetX * GRID_SIZE;
+ float deltaZ = gridOriginZ - offsetZ * GRID_SIZE;
+
+ // Calculate the density at this grid cell
+ float scaledDistance = MathHelper.sqrt(deltaX * deltaX + deltaZ * deltaZ) * distanceFactor;
+ float densityHere = ISLAND_RADIUS - scaledDistance;
+
+ // Try to return early if we're over the max
+ if (densityHere > density) {
+ if (densityHere >= MAX) {
+ return MAX;
+ }
+
+ density = densityHere;
+ }
+ }
+ }
+ }
+
+ // Avoid a call to Math.max because the density cannot be bigger than the max.
+ if (density < MIN) {
+ return MIN;
+ }
+
+ return density;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java b/src/main/java/net/minecraft/server/ChunkGeneratorAbstract.java
index 45b771e4121f2ef27c67d5a5ba2dadcfc0f944e0..448745b9e499b86f3ce6938c0f0fb0fbb222a781 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 me.jellysquid.mods.lithium.common.world.noise.SimplexNoiseCache;
+
import java.util.Iterator;
import java.util.List;
import java.util.Random;
@@ -56,12 +58,13 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
private final NoiseGenerator t;
private final NoiseGeneratorOctaves u;
@Nullable
- private final NoiseGenerator3Handler v;
+ private final NoiseGenerator3Handler v; // Yatopia Note: yarn "SimplexNoiseSampler"
protected final IBlockData f;
protected final IBlockData g;
private final long w;
protected final GeneratorSettingBase h;
private final int x;
+ private ThreadLocal<SimplexNoiseCache> tlCache; // Yatopia: lithium
public ChunkGeneratorAbstract(WorldChunkManager worldchunkmanager, long i, GeneratorSettingBase generatorsettingbase) {
this(worldchunkmanager, worldchunkmanager, i, generatorsettingbase);
@@ -96,7 +99,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
} else {
this.v = null;
}
-
+ this.tlCache = ThreadLocal.withInitial(() -> new SimplexNoiseCache(v)); // Yapfa: lithium
}
@Override
@@ -161,7 +164,7 @@ public final class ChunkGeneratorAbstract extends ChunkGenerator {
double d3;
if (this.v != null) {
- d0 = (double) (WorldChunkManagerTheEnd.a(this.v, i, j) - 8.0F);
+ d0 = (double) (/*WorldChunkManagerTheEnd.a(this.v, i, j) Yatopia lithium*/tlCache.get().getNoiseAt(i, j) - 8.0F);
if (d0 > 0.0D) {
d1 = 0.25D;
} else {