c5a10665b8
Spigot still maintains some partial implementation of "tick skipping", a practice in which the MinecraftServer.currentTick field is updated not by an increment of one per actual tick, but instead set to System.currentTimeMillis() / 50. This behaviour means that the tracked tick may "skip" a tick value in case a previous tick took more than the expected 50ms. To compensate for this in important paths, spigot/craftbukkit implements "wall-time". Instead of incrementing/decrementing ticks on block entities/entities by one for each call to their tick() method, they instead increment/decrement important values, like an ItemEntity's age or pickupDelay, by the difference of `currentTick - lastTick`, where `lastTick` is the value of `currentTick` during the last tick() call. These "fixes" however do not play nicely with minecraft's simulation distance as entities/block entities implementing the above behaviour would "catch up" their values when moving from a non-ticking chunk to a ticking one as their `lastTick` value remains stuck on the last tick in a ticking chunk and hence lead to a large "catch up" once ticked again. Paper completely removes the "tick skipping" behaviour (See patch "Further-improve-server-tick-loop"), making the above precautions completely unnecessary, which also rids paper of the previous described incompatibility with non-ticking chunks.
64 Zeilen
3.8 KiB
Diff
64 Zeilen
3.8 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com>
|
|
Date: Tue, 3 Nov 2020 23:48:05 -0600
|
|
Subject: [PATCH] Significantly improve performance of the end generation
|
|
|
|
This patch implements a noise cache for the end which significantly reduces the computation time of generation. This results in about a 3x improvement.
|
|
|
|
Original code by SuperCoder7979 and Gegy in Lithium, licensed under LGPL-3.0 (Source: https://github.com/jellysquid3/lithium-fabric)
|
|
|
|
Co-authored-by: Gegy <gegy1000@gmail.com>
|
|
Co-authored-by: Dylan Xaldin <Puremin0rez515@gmail.com>
|
|
Co-authored-by: pop4959 <pop4959@gmail.com>
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/levelgen/DensityFunctions.java b/src/main/java/net/minecraft/world/level/levelgen/DensityFunctions.java
|
|
index b09bc1dac649ce9f4826edc1923c843804226993..ac8447e20531ad59d5e26c6db541d6e844d56c0f 100644
|
|
--- a/src/main/java/net/minecraft/world/level/levelgen/DensityFunctions.java
|
|
+++ b/src/main/java/net/minecraft/world/level/levelgen/DensityFunctions.java
|
|
@@ -509,6 +509,16 @@ public final class DensityFunctions {
|
|
);
|
|
private static final float ISLAND_THRESHOLD = -0.9F;
|
|
private final SimplexNoise islandNoise;
|
|
+ // Paper start - Perf: Optimize end generation
|
|
+ private static final class NoiseCache {
|
|
+ public long[] keys = new long[8192];
|
|
+ public float[] values = new float[8192];
|
|
+ public NoiseCache() {
|
|
+ java.util.Arrays.fill(keys, Long.MIN_VALUE);
|
|
+ }
|
|
+ }
|
|
+ private static final ThreadLocal<java.util.Map<SimplexNoise, NoiseCache>> noiseCache = ThreadLocal.withInitial(java.util.WeakHashMap::new);
|
|
+ // Paper end - Perf: Optimize end generation
|
|
|
|
public EndIslandDensityFunction(long seed) {
|
|
RandomSource randomSource = new LegacyRandomSource(seed);
|
|
@@ -524,12 +534,26 @@ public final class DensityFunctions {
|
|
float f = 100.0F - Mth.sqrt((long) x * (long) x + (long) z * (long) z) * 8.0F; // Paper - cast ints to long to avoid integer overflow
|
|
f = Mth.clamp(f, -100.0F, 80.0F);
|
|
|
|
+ NoiseCache cache = noiseCache.get().computeIfAbsent(sampler, noiseKey -> new NoiseCache()); // Paper - Perf: Optimize end generation
|
|
for (int m = -12; m <= 12; m++) {
|
|
for (int n = -12; n <= 12; n++) {
|
|
long o = (long)(i + m);
|
|
long p = (long)(j + n);
|
|
- if (o * o + p * p > 4096L && sampler.getValue((double)o, (double)p) < -0.9F) {
|
|
- float g = (Mth.abs((float)o) * 3439.0F + Mth.abs((float)p) * 147.0F) % 13.0F + 9.0F;
|
|
+ // Paper start - Perf: Optimize end generation by using a noise cache
|
|
+ long key = net.minecraft.world.level.ChunkPos.asLong((int) o, (int) p);
|
|
+ int index = (int) it.unimi.dsi.fastutil.HashCommon.mix(key) & 8191;
|
|
+ float g = Float.MIN_VALUE;
|
|
+ if (cache.keys[index] == key) {
|
|
+ g = cache.values[index];
|
|
+ } else {
|
|
+ if (o * o + p * p > 4096L && sampler.getValue((double)o, (double)p) < -0.9F) {
|
|
+ g = (Mth.abs((float)o) * 3439.0F + Mth.abs((float)p) * 147.0F) % 13.0F + 9.0F;
|
|
+ }
|
|
+ cache.keys[index] = key;
|
|
+ cache.values[index] = g;
|
|
+ }
|
|
+ if (g != Float.MIN_VALUE) {
|
|
+ // Paper end - Perf: Optimize end generation
|
|
float h = (float)(k - m * 2);
|
|
float q = (float)(l - n * 2);
|
|
float r = 100.0F - Mth.sqrt(h * h + q * q) * g;
|