mirror of
https://github.com/LeavesMC/Leaves.git
synced 2025-12-27 02:49:10 +00:00
Update 1.20.2 (#139)
This commit is contained in:
230
patches/server/0038-Use-aging-cache-for-biome-temperatures.patch
Normal file
230
patches/server/0038-Use-aging-cache-for-biome-temperatures.patch
Normal file
@@ -0,0 +1,230 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
||||
Date: Thu, 18 Aug 2022 16:53:45 +0800
|
||||
Subject: [PATCH] Use aging cache for biome temperatures
|
||||
|
||||
This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/biome/Biome.java b/src/main/java/net/minecraft/world/level/biome/Biome.java
|
||||
index 65012a12e1430956ef55ced56773e6354ac26444..fe43432da26a3570c993b5592b7b8020331bdb74 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/biome/Biome.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/biome/Biome.java
|
||||
@@ -66,23 +66,37 @@ public final class Biome {
|
||||
private final BiomeGenerationSettings generationSettings;
|
||||
private final MobSpawnSettings mobSettings;
|
||||
private final BiomeSpecialEffects specialEffects;
|
||||
- private final ThreadLocal<Long2FloatLinkedOpenHashMap> temperatureCache = ThreadLocal.withInitial(() -> {
|
||||
- return Util.make(() -> {
|
||||
- Long2FloatLinkedOpenHashMap long2FloatLinkedOpenHashMap = new Long2FloatLinkedOpenHashMap(1024, 0.25F) {
|
||||
- protected void rehash(int i) {
|
||||
- }
|
||||
- };
|
||||
- long2FloatLinkedOpenHashMap.defaultReturnValue(Float.NaN);
|
||||
- return long2FloatLinkedOpenHashMap;
|
||||
- });
|
||||
- });
|
||||
+ // Leaves start - use our cache
|
||||
+ private final ThreadLocal<Long2FloatLinkedOpenHashMap> temperatureCache;
|
||||
+ private final ThreadLocal<top.leavesmc.leaves.structs.Long2FloatAgingCache> temperatureAgingCache;
|
||||
|
||||
Biome(Biome.ClimateSettings weather, BiomeSpecialEffects effects, BiomeGenerationSettings generationSettings, MobSpawnSettings spawnSettings) {
|
||||
this.climateSettings = weather;
|
||||
this.generationSettings = generationSettings;
|
||||
this.mobSettings = spawnSettings;
|
||||
this.specialEffects = effects;
|
||||
+ if (top.leavesmc.leaves.LeavesConfig.biomeTemperaturesUseAgingCache) {
|
||||
+ temperatureCache = null;
|
||||
+ temperatureAgingCache = ThreadLocal.withInitial(() -> {
|
||||
+ return Util.make(() -> {
|
||||
+ return new top.leavesmc.leaves.structs.Long2FloatAgingCache(TEMPERATURE_CACHE_SIZE);
|
||||
+ });
|
||||
+ });
|
||||
+ } else {
|
||||
+ temperatureCache = ThreadLocal.withInitial(() -> {
|
||||
+ return Util.make(() -> {
|
||||
+ Long2FloatLinkedOpenHashMap long2FloatLinkedOpenHashMap = new Long2FloatLinkedOpenHashMap(1024, 0.25F) {
|
||||
+ protected void rehash(int i) {
|
||||
+ }
|
||||
+ };
|
||||
+ long2FloatLinkedOpenHashMap.defaultReturnValue(Float.NaN);
|
||||
+ return long2FloatLinkedOpenHashMap;
|
||||
+ });
|
||||
+ });
|
||||
+ temperatureAgingCache = null;
|
||||
+ }
|
||||
}
|
||||
+ // Leaves end - use our cache
|
||||
|
||||
public int getSkyColor() {
|
||||
return this.specialEffects.getSkyColor();
|
||||
@@ -118,19 +132,33 @@ public final class Biome {
|
||||
@Deprecated
|
||||
public float getTemperature(BlockPos blockPos) {
|
||||
long l = blockPos.asLong();
|
||||
- Long2FloatLinkedOpenHashMap long2FloatLinkedOpenHashMap = this.temperatureCache.get();
|
||||
- float f = long2FloatLinkedOpenHashMap.get(l);
|
||||
- if (!Float.isNaN(f)) {
|
||||
- return f;
|
||||
- } else {
|
||||
- float g = this.getHeightAdjustedTemperature(blockPos);
|
||||
- if (long2FloatLinkedOpenHashMap.size() == 1024) {
|
||||
- long2FloatLinkedOpenHashMap.removeFirstFloat();
|
||||
+ // Leaves start - use our cache
|
||||
+ if (top.leavesmc.leaves.LeavesConfig.biomeTemperaturesUseAgingCache) {
|
||||
+ top.leavesmc.leaves.structs.Long2FloatAgingCache cache = this.temperatureAgingCache.get();
|
||||
+ float f = cache.getValue(l);
|
||||
+ if (!Float.isNaN(f)) {
|
||||
+ return f;
|
||||
+ } else {
|
||||
+ float g = this.getHeightAdjustedTemperature(blockPos);
|
||||
+ cache.putValue(l, g);
|
||||
+ return g;
|
||||
}
|
||||
+ } else {
|
||||
+ Long2FloatLinkedOpenHashMap long2FloatLinkedOpenHashMap = this.temperatureCache.get();
|
||||
+ float f = long2FloatLinkedOpenHashMap.get(l);
|
||||
+ if (!Float.isNaN(f)) {
|
||||
+ return f;
|
||||
+ } else {
|
||||
+ float g = this.getHeightAdjustedTemperature(blockPos);
|
||||
+ if (long2FloatLinkedOpenHashMap.size() == 1024) {
|
||||
+ long2FloatLinkedOpenHashMap.removeFirstFloat();
|
||||
+ }
|
||||
|
||||
- long2FloatLinkedOpenHashMap.put(l, g);
|
||||
- return g;
|
||||
+ long2FloatLinkedOpenHashMap.put(l, g);
|
||||
+ return g;
|
||||
+ }
|
||||
}
|
||||
+ // Leaves end - use our cache
|
||||
}
|
||||
|
||||
public boolean shouldFreeze(LevelReader world, BlockPos blockPos) {
|
||||
diff --git a/src/main/java/top/leavesmc/leaves/structs/Long2FloatAgingCache.java b/src/main/java/top/leavesmc/leaves/structs/Long2FloatAgingCache.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..26f9d4d9099739d6ddc159184a20e2ae9abde5cd
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/top/leavesmc/leaves/structs/Long2FloatAgingCache.java
|
||||
@@ -0,0 +1,121 @@
|
||||
+package top.leavesmc.leaves.structs;
|
||||
+
|
||||
+import it.unimi.dsi.fastutil.HashCommon;
|
||||
+
|
||||
+// Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish)
|
||||
+
|
||||
+/**
|
||||
+ * A replacement for the cache used in Biome.
|
||||
+ */
|
||||
+public class Long2FloatAgingCache {
|
||||
+
|
||||
+ private static class AgingEntry {
|
||||
+ private long data;
|
||||
+ private float value;
|
||||
+ private int uses = 0;
|
||||
+ private int age = 0;
|
||||
+
|
||||
+ private AgingEntry(long data, float value) {
|
||||
+ this.data = data;
|
||||
+ this.value = value;
|
||||
+ }
|
||||
+
|
||||
+ public void replace(long data, float flag) {
|
||||
+ this.data = data;
|
||||
+ this.value = flag;
|
||||
+ }
|
||||
+
|
||||
+ public int getValue() {
|
||||
+ return this.uses - (this.age >> 1); // age isn't as important as uses
|
||||
+ }
|
||||
+
|
||||
+ public void incrementUses() {
|
||||
+ this.uses = this.uses + 1 & Integer.MAX_VALUE;
|
||||
+ }
|
||||
+
|
||||
+ public void incrementAge() {
|
||||
+ this.age = this.age + 1 & Integer.MAX_VALUE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private final AgingEntry[] entries;
|
||||
+ private final int mask;
|
||||
+ private final int maxDistance; // the most amount of entries to check for a value
|
||||
+
|
||||
+ public Long2FloatAgingCache(int size) {
|
||||
+ int arraySize = HashCommon.nextPowerOfTwo(size);
|
||||
+ this.entries = new AgingEntry[arraySize];
|
||||
+ this.mask = arraySize - 1;
|
||||
+ this.maxDistance = Math.min(arraySize, 4);
|
||||
+ }
|
||||
+
|
||||
+ public float getValue(long data) {
|
||||
+ AgingEntry curr;
|
||||
+ int pos;
|
||||
+
|
||||
+ if ((curr = this.entries[pos = HashCommon.mix(HashCommon.long2int(data)) & this.mask]) == null) {
|
||||
+ return Float.NaN;
|
||||
+ } else if (data == curr.data) {
|
||||
+ curr.incrementUses();
|
||||
+ return curr.value;
|
||||
+ }
|
||||
+
|
||||
+ int checked = 1; // start at 1 because we already checked the first spot above
|
||||
+
|
||||
+ while ((curr = this.entries[pos = (pos + 1) & this.mask]) != null) {
|
||||
+ if (data == curr.data) {
|
||||
+ curr.incrementUses();
|
||||
+ return curr.value;
|
||||
+ } else if (++checked >= this.maxDistance) {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return Float.NaN;
|
||||
+ }
|
||||
+
|
||||
+ public void putValue(long data, float value) {
|
||||
+ AgingEntry curr;
|
||||
+ int pos;
|
||||
+
|
||||
+ if ((curr = this.entries[pos = HashCommon.mix(HashCommon.long2int(data)) & this.mask]) == null) {
|
||||
+ this.entries[pos] = new AgingEntry(data, value); // add
|
||||
+ return;
|
||||
+ } else if (data == curr.data) {
|
||||
+ curr.incrementUses();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ int checked = 1; // start at 1 because we already checked the first spot above
|
||||
+
|
||||
+ while ((curr = this.entries[pos = (pos + 1) & this.mask]) != null) {
|
||||
+ if (data == curr.data) {
|
||||
+ curr.incrementUses();
|
||||
+ return;
|
||||
+ } else if (++checked >= this.maxDistance) {
|
||||
+ this.forceAdd(data, value);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ this.entries[pos] = new AgingEntry(data, value); // add
|
||||
+ }
|
||||
+
|
||||
+ private void forceAdd(long data, float value) {
|
||||
+ int expectedPos = HashCommon.mix(HashCommon.long2int(data)) & this.mask;
|
||||
+ AgingEntry entryToRemove = this.entries[expectedPos];
|
||||
+
|
||||
+ for (int i = expectedPos + 1; i < expectedPos + this.maxDistance; i++) {
|
||||
+ int pos = i & this.mask;
|
||||
+ AgingEntry entry = this.entries[pos];
|
||||
+ if (entry.getValue() < entryToRemove.getValue()) {
|
||||
+ entryToRemove = entry;
|
||||
+ }
|
||||
+
|
||||
+ entry.incrementAge(); // use this as a mechanism to age the other entries
|
||||
+ }
|
||||
+
|
||||
+ // remove the least used/oldest entry
|
||||
+ entryToRemove.replace(data, value);
|
||||
+ }
|
||||
+}
|
||||
Reference in New Issue
Block a user