mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
165 lines
7.0 KiB
Diff
165 lines
7.0 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Taiyou06 <kaandindar21@gmail.com>
|
|
Date: Fri, 8 Nov 2024 00:06:34 +0100
|
|
Subject: [PATCH] Lithium: IterateOutwardsCache
|
|
|
|
By: 2No2Name <2No2Name@web.de>
|
|
As part of: Lithium (https://github.com/CaffeineMC/lithium-fabric)
|
|
Licensed under: LGPL-3.0 (https://www.gnu.org/licenses/lgpl-3.0.html)
|
|
|
|
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
|
|
index a64e5997b94cc8173f0512d1e282355f14f098ec..1d0f67e10a061225dfe99cbd935c4fb5a4cbe22b 100644
|
|
--- a/src/main/java/net/minecraft/core/BlockPos.java
|
|
+++ b/src/main/java/net/minecraft/core/BlockPos.java
|
|
@@ -343,7 +343,19 @@ public class BlockPos extends Vec3i {
|
|
};
|
|
}
|
|
|
|
+ // JettPack start - lithium: cached iterate outwards
|
|
+ private static final org.dreeam.leaf.util.cache.IterateOutwardsCache ITERATE_OUTWARDS_CACHE = new org.dreeam.leaf.util.cache.IterateOutwardsCache(50);
|
|
+ private static final it.unimi.dsi.fastutil.longs.LongList HOGLIN_PIGLIN_CACHE = ITERATE_OUTWARDS_CACHE.getOrCompute(8, 4, 8);
|
|
+ // JettPack end
|
|
+
|
|
+
|
|
public static Iterable<BlockPos> withinManhattan(BlockPos center, int rangeX, int rangeY, int rangeZ) {
|
|
+ // JettPack start - lithium: cached iterate outwards
|
|
+ if (center != org.dreeam.leaf.util.cache.IterateOutwardsCache.POS_ZERO) {
|
|
+ final it.unimi.dsi.fastutil.longs.LongList positions = rangeX == 8 && rangeY == 4 && rangeZ == 8 ? HOGLIN_PIGLIN_CACHE : ITERATE_OUTWARDS_CACHE.getOrCompute(rangeX, rangeY, rangeZ);
|
|
+ return new org.dreeam.leaf.util.cache.LongList2BlockPosMutableIterable(center, positions);
|
|
+ }
|
|
+ // JettPack end
|
|
int i = rangeX + rangeY + rangeZ;
|
|
// Paper start - rename variables to fix conflict with anonymous class (remap fix)
|
|
int centerX = center.getX();
|
|
diff --git a/src/main/java/org/dreeam/leaf/util/cache/IterateOutwardsCache.java b/src/main/java/org/dreeam/leaf/util/cache/IterateOutwardsCache.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..9ae6b0a5e1e1c8584a982b1dbd65da3f2de38eaa
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/dreeam/leaf/util/cache/IterateOutwardsCache.java
|
|
@@ -0,0 +1,71 @@
|
|
+package org.dreeam.leaf.util.cache;
|
|
+
|
|
+import it.unimi.dsi.fastutil.longs.LongArrayList;
|
|
+import it.unimi.dsi.fastutil.longs.LongList;
|
|
+import java.util.Iterator;
|
|
+import java.util.Random;
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
+import net.minecraft.core.BlockPos;
|
|
+
|
|
+/**
|
|
+ * @author 2No2Name, original implemenation by SuperCoder7979 and Gegy1000
|
|
+ */
|
|
+public class IterateOutwardsCache {
|
|
+ //POS_ZERO must not be replaced with BlockPos.ORIGIN, otherwise iterateOutwards at BlockPos.ORIGIN will not use the cache
|
|
+ public static final BlockPos POS_ZERO = new BlockPos(0,0,0);
|
|
+
|
|
+
|
|
+ private final ConcurrentHashMap<Long, LongArrayList> table;
|
|
+ private final int capacity;
|
|
+ private final Random random;
|
|
+
|
|
+ public IterateOutwardsCache(int capacity) {
|
|
+ this.capacity = capacity;
|
|
+ this.table = new ConcurrentHashMap<>(31);
|
|
+ this.random = new Random();
|
|
+ }
|
|
+
|
|
+ private void fillPositionsWithIterateOutwards(LongList entry, int xRange, int yRange, int zRange) {
|
|
+ // Add all positions to the cached list
|
|
+ for (BlockPos pos : BlockPos.withinManhattan(POS_ZERO, xRange, yRange, zRange)) {
|
|
+ entry.add(pos.asLong());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public LongList getOrCompute(int xRange, int yRange, int zRange) {
|
|
+ long key = BlockPos.asLong(xRange, yRange, zRange);
|
|
+
|
|
+ LongArrayList entry = this.table.get(key);
|
|
+ if (entry != null) {
|
|
+ return entry;
|
|
+ }
|
|
+
|
|
+ // Cache miss: compute and store
|
|
+ entry = new LongArrayList(128);
|
|
+
|
|
+ this.fillPositionsWithIterateOutwards(entry, xRange, yRange, zRange);
|
|
+
|
|
+ //decrease the array size, as of now it won't be modified anymore anyways
|
|
+ entry.trim();
|
|
+
|
|
+ //this might overwrite an entry as the same entry could have been computed and added during this thread's computation
|
|
+ //we do not use computeIfAbsent, as it can delay other threads for too long
|
|
+ Object previousEntry = this.table.put(key, entry);
|
|
+
|
|
+
|
|
+ if (previousEntry == null && this.table.size() > this.capacity) {
|
|
+ //prevent a memory leak by randomly removing about 1/8th of the elements when the exceed the desired capacity is exceeded
|
|
+ final Iterator<Long> iterator = this.table.keySet().iterator();
|
|
+ //prevent an unlikely infinite loop caused by another thread filling the table concurrently using counting
|
|
+ for (int i = -this.capacity; iterator.hasNext() && i < 5; i++) {
|
|
+ Long key2 = iterator.next();
|
|
+ //random is not threadsafe, but it doesn't matter here, because we don't need quality random numbers
|
|
+ if (this.random.nextInt(8) == 0 && key2 != key) {
|
|
+ iterator.remove();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return entry;
|
|
+ }
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/src/main/java/org/dreeam/leaf/util/cache/LongList2BlockPosMutableIterable.java b/src/main/java/org/dreeam/leaf/util/cache/LongList2BlockPosMutableIterable.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..bdc1e6a9093dd403e9acacf1ffea873c4738f8ec
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/dreeam/leaf/util/cache/LongList2BlockPosMutableIterable.java
|
|
@@ -0,0 +1,46 @@
|
|
+package org.dreeam.leaf.util.cache;
|
|
+
|
|
+import it.unimi.dsi.fastutil.longs.LongIterator;
|
|
+import it.unimi.dsi.fastutil.longs.LongList;
|
|
+import java.util.Iterator;
|
|
+import net.minecraft.core.BlockPos;
|
|
+
|
|
+/**
|
|
+ * @author 2No2Name
|
|
+ */
|
|
+public class LongList2BlockPosMutableIterable implements Iterable<BlockPos> {
|
|
+
|
|
+ private final LongList positions;
|
|
+ private final int xOffset, yOffset, zOffset;
|
|
+
|
|
+ public LongList2BlockPosMutableIterable(BlockPos offset, LongList posList) {
|
|
+ this.xOffset = offset.getX();
|
|
+ this.yOffset = offset.getY();
|
|
+ this.zOffset = offset.getZ();
|
|
+ this.positions = posList;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Iterator<BlockPos> iterator() {
|
|
+ return new Iterator<BlockPos>() {
|
|
+
|
|
+ private final LongIterator it = LongList2BlockPosMutableIterable.this.positions.iterator();
|
|
+ private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
|
+
|
|
+ @Override
|
|
+ public boolean hasNext() {
|
|
+ return it.hasNext();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public net.minecraft.core.BlockPos next() {
|
|
+ long nextPos = this.it.nextLong();
|
|
+ return this.pos.set(
|
|
+ LongList2BlockPosMutableIterable.this.xOffset + BlockPos.getX(nextPos),
|
|
+ LongList2BlockPosMutableIterable.this.yOffset + BlockPos.getY(nextPos),
|
|
+ LongList2BlockPosMutableIterable.this.zOffset + BlockPos.getZ(nextPos));
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+
|
|
+}
|
|
\ No newline at end of file
|