diff --git a/README.md b/README.md index 5c55b52e..428aa55f 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ If these excellent projects hadn't appeared, Leaf wouldn't have become great. • Luminol
Nitori
Moonrise
+ • DivineMC

diff --git a/patches/server/0127-Asynchronous-locator.patch b/patches/server/0126-Asynchronous-locator.patch similarity index 100% rename from patches/server/0127-Asynchronous-locator.patch rename to patches/server/0126-Asynchronous-locator.patch diff --git a/patches/server/0128-Virtual-thread-for-chat-executor.patch b/patches/server/0127-Virtual-thread-for-chat-executor.patch similarity index 94% rename from patches/server/0128-Virtual-thread-for-chat-executor.patch rename to patches/server/0127-Virtual-thread-for-chat-executor.patch index 5bb5d294..631ae0dd 100644 --- a/patches/server/0128-Virtual-thread-for-chat-executor.patch +++ b/patches/server/0127-Virtual-thread-for-chat-executor.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Virtual thread for chat executor diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f268001f7a821ad1d0db8a02de19e80cc951d0fd..279289e0c3dc65fed0ee4b2f5b0ef077ab433d5e 100644 +index 37c377761b45eefab39164a7e714e585a02a4447..09e55f62b4cea5b058e04356252f4f56957646b8 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2900,7 +2900,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop +Date: Fri, 8 Nov 2024 00:22:44 +0800 +Subject: [PATCH] DivineMC - Lithium: entity.fast_elytra_check + + entity.fast_hand_swing + +Original license: GPL v3 +Original project: https://github.com/DivineMC/DivineMC + +Original license: LGPL v3 +Original project: https://github.com/CaffeineMC/lithium-fabric + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 241e2598973939b7d19768cd9ca7cd8f3818c053..7ce6ce7212b942a8d6b64c98fab8fe060d813c61 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -2769,6 +2769,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + } + + protected void updateSwingTime() { ++ if (!this.swinging && this.swingTime == 0) return; // DivineMC - Lithium: entity.fast_hand_swing + int i = this.getCurrentSwingDuration(); + + if (this.swinging) { +@@ -3747,6 +3748,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + } + + private void updateFallFlying() { ++ if (!this.isFallFlying()) return; // DivineMC - Lithium: entity.fast_elytra_check + boolean flag = this.getSharedFlag(7); + + if (flag && !this.onGround() && !this.isPassenger() && !this.hasEffect(MobEffects.LEVITATION)) { diff --git a/patches/server/0136-C2ME-Reduce-Allocations.patch b/patches/server/0136-C2ME-Reduce-Allocations.patch new file mode 100644 index 00000000..614c94db --- /dev/null +++ b/patches/server/0136-C2ME-Reduce-Allocations.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Thu, 7 Nov 2024 19:45:31 +0100 +Subject: [PATCH] C2ME-Reduce-Allocations + + +diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/OreFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/OreFeature.java +index 506b2afd099c9b7e9ac3f6f2fcea8e523fae396b..b6a5f3e8105f0fe210ee1d33500fba45d0bb9462 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/feature/OreFeature.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/feature/OreFeature.java +@@ -69,7 +69,7 @@ public class OreFeature extends Feature { + int verticalSize + ) { + int i = 0; +- BitSet bitSet = new BitSet(horizontalSize * verticalSize * horizontalSize); ++ BitSet bitSet = org.dreeam.leaf.util.cache.CachedOrNewBitsGetter.getCachedOrNewBitSet(horizontalSize * verticalSize * horizontalSize); // DivineMC - C2ME: reduce_allocs - Leaf + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + int j = config.size; + double[] ds = new double[j * 4]; +diff --git a/src/main/java/org/dreeam/leaf/util/cache/CachedOrNewBitsGetter.java b/src/main/java/org/dreeam/leaf/util/cache/CachedOrNewBitsGetter.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e039cc46a2078bb0cd01b41ddc26437d8be56c64 +--- /dev/null ++++ b/src/main/java/org/dreeam/leaf/util/cache/CachedOrNewBitsGetter.java +@@ -0,0 +1,20 @@ ++package org.dreeam.leaf.util.cache; ++ ++import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; ++ ++import java.util.BitSet; ++import java.util.function.IntFunction; ++ ++public class CachedOrNewBitsGetter { ++ private static final IntFunction bitSetConstructor = BitSet::new; ++ ++ public static ThreadLocal> BITSETS = ThreadLocal.withInitial(Int2ObjectOpenHashMap::new); ++ ++ private CachedOrNewBitsGetter() {} ++ ++ public static BitSet getCachedOrNewBitSet(int bits) { ++ final BitSet bitSet = BITSETS.get().computeIfAbsent(bits, bitSetConstructor); ++ bitSet.clear(); ++ return bitSet; ++ } ++} +\ No newline at end of file diff --git a/patches/server/0137-Lithium-fast-util.patch b/patches/server/0137-Lithium-fast-util.patch new file mode 100644 index 00000000..c24c2958 --- /dev/null +++ b/patches/server/0137-Lithium-fast-util.patch @@ -0,0 +1,84 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Thu, 7 Nov 2024 21:50:47 +0100 +Subject: [PATCH] Lithium-fast-util + + +diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java +index f15dd2ccb99ade10ac1e49b63e6f4080bd39b3c9..bc6bc48386c8b56aaacd743d689ddf4375e60563 100644 +--- a/src/main/java/net/minecraft/core/Direction.java ++++ b/src/main/java/net/minecraft/core/Direction.java +@@ -204,7 +204,7 @@ public enum Direction implements StringRepresentable, ca.spottedleaf.moonrise.pa + } + + public Direction getOpposite() { +- return this.opposite; // Paper - optimise collisions ++ return VALUES[this.oppositeIndex]; // JettPack - lithium: fast util + } + + public Direction getClockWise(Direction.Axis axis) { +@@ -366,7 +366,7 @@ public enum Direction implements StringRepresentable, ca.spottedleaf.moonrise.pa + } + + public static Direction getRandom(RandomSource random) { +- return Util.getRandom(VALUES, random); ++ return VALUES[random.nextInt(VALUES.length)]; // JettPack - lithium: fast util + } + + public static Direction getNearest(double x, double y, double z) { +diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java +index db78616676ba021ee0f03cfea932f2912f4ec987..b6e26cca54b7f429312b45137714fba59db5e418 100644 +--- a/src/main/java/net/minecraft/world/phys/AABB.java ++++ b/src/main/java/net/minecraft/world/phys/AABB.java +@@ -17,6 +17,15 @@ public class AABB { + public final double maxY; + public final double maxZ; + ++ // JettPack start - lithium: fast_util ++ static { ++ assert Direction.Axis.X.ordinal() == 0; ++ assert Direction.Axis.Y.ordinal() == 1; ++ assert Direction.Axis.Z.ordinal() == 2; ++ assert Direction.Axis.values().length == 3; ++ } ++ // JettPack end ++ + public AABB(double x1, double y1, double z1, double x2, double y2, double z2) { + this.minX = Math.min(x1, x2); + this.minY = Math.min(y1, y2); +@@ -85,11 +94,33 @@ public class AABB { + } + + public double min(Direction.Axis axis) { +- return axis.choose(this.minX, this.minY, this.minZ); ++ // JettPack start - lithium: fast_util ++ switch (axis.ordinal()) { ++ case 0: //X ++ return this.minX; ++ case 1: //Y ++ return this.minY; ++ case 2: //Z ++ return this.minZ; ++ } ++ ++ throw new IllegalArgumentException(); ++ // JettPack end + } + + public double max(Direction.Axis axis) { +- return axis.choose(this.maxX, this.maxY, this.maxZ); ++ // JettPack start - lithium: fast_util ++ switch (axis.ordinal()) { ++ case 0: //X ++ return this.maxX; ++ case 1: //Y ++ return this.maxY; ++ case 2: //Z ++ return this.maxZ; ++ } ++ ++ throw new IllegalArgumentException(); ++ // JettPack end + } + + @Override diff --git a/patches/server/0138-Lithium-CompactSineLUT.patch b/patches/server/0138-Lithium-CompactSineLUT.patch new file mode 100644 index 00000000..095c00d4 --- /dev/null +++ b/patches/server/0138-Lithium-CompactSineLUT.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Thu, 7 Nov 2024 23:51:51 +0100 +Subject: [PATCH] Lithium-CompactSineLUT + + +diff --git a/src/main/java/net/minecraft/util/Mth.java b/src/main/java/net/minecraft/util/Mth.java +index cb8cde3c1b65329f92b7c78e529e128f5a408fd6..ac359e7237ff6256045ee47ca287d9315900dc0e 100644 +--- a/src/main/java/net/minecraft/util/Mth.java ++++ b/src/main/java/net/minecraft/util/Mth.java +@@ -35,6 +35,7 @@ public class Mth { + } + }); + private static final RandomSource RANDOM = RandomSource.createThreadSafe(); ++ public static float[] getSinTable() { return SIN; } // Mirai - lithium: CompactSineLUT + private static final int[] MULTIPLY_DE_BRUIJN_BIT_POSITION = new int[]{ + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; +@@ -46,11 +47,11 @@ public class Mth { + private static final double[] COS_TAB = new double[257]; + + public static float sin(float value) { +- return SIN[(int)(value * 10430.378F) & 65535]; ++ return org.dreeam.leaf.math.CompactSineLUT.sin(value); // Mirai - lithium: CompactSineLUT + } + + public static float cos(float value) { +- return SIN[(int)(value * 10430.378F + 16384.0F) & 65535]; ++ return org.dreeam.leaf.math.CompactSineLUT.cos(value); // Mirai - lithium: CompactSineLUT + } + + public static float sqrt(float value) { +diff --git a/src/main/java/org/dreeam/leaf/math/CompactSineLUT.java b/src/main/java/org/dreeam/leaf/math/CompactSineLUT.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e07833e77f65eb1b250879580c481cea51c840a8 +--- /dev/null ++++ b/src/main/java/org/dreeam/leaf/math/CompactSineLUT.java +@@ -0,0 +1,90 @@ ++package org.dreeam.leaf.math; ++ ++import net.minecraft.util.Mth; ++ ++/** ++ * A replacement for the sine angle lookup table used in {@link Mth}, both reducing the size of LUT and improving ++ * the access patterns for common paired sin/cos operations. ++ * ++ * sin(-x) = -sin(x) ++ * ... to eliminate negative angles from the LUT. ++ * ++ * sin(x) = sin(pi/2 - x) ++ * ... to eliminate supplementary angles from the LUT. ++ * ++ * Using these identities allows us to reduce the LUT from 64K entries (256 KB) to just 16K entries (64 KB), enabling ++ * it to better fit into the CPU's caches at the expense of some cycles on the fast path. The implementation has been ++ * tightly optimized to avoid branching where possible and to use very quick integer operations. ++ * ++ * Generally speaking, reducing the size of a lookup table is always a good optimization, but since we need to spend ++ * extra CPU cycles trying to maintain parity with vanilla, there is the potential risk that this implementation ends ++ * up being slower than vanilla when the lookup table is able to be kept in cache memory. ++ * ++ * Unlike other "fast math" implementations, the values returned by this class are *bit-for-bit identical* with those ++ * from {@link Mth}. Validation is performed during runtime to ensure that the table is correct. ++ * ++ * @author coderbot16 Author of the original (and very clever) implementation in Rust: ++ * https://gitlab.com/coderbot16/i73/-/tree/master/i73-trig/src ++ * @author jellysquid3 Additional optimizations, port to Java ++ */ ++public class CompactSineLUT { ++ private static final int[] SINE_TABLE_INT = new int[16384 + 1]; ++ private static final float SINE_TABLE_MIDPOINT; ++ ++ static { ++ final float[] SINE_TABLE = Mth.getSinTable(); ++ // Copy the sine table, covering to raw int bits ++ for (int i = 0; i < SINE_TABLE_INT.length; i++) { ++ SINE_TABLE_INT[i] = Float.floatToRawIntBits(SINE_TABLE[i]); ++ } ++ ++ SINE_TABLE_MIDPOINT = SINE_TABLE[SINE_TABLE.length / 2]; ++ ++ // Test that the lookup table is correct during runtime ++ for (int i = 0; i < SINE_TABLE.length; i++) { ++ float expected = SINE_TABLE[i]; ++ float value = lookup(i); ++ ++ if (expected != value) { ++ throw new IllegalArgumentException(String.format("LUT error at index %d (expected: %s, found: %s)", i, expected, value)); ++ } ++ } ++ } ++ ++ // [VanillaCopy] MathHelper#sin(float) ++ public static float sin(float f) { ++ return lookup((int) (f * 10430.378f) & 0xFFFF); ++ } ++ ++ // [VanillaCopy] MathHelper#cos(float) ++ public static float cos(float f) { ++ return lookup((int) (f * 10430.378f + 16384.0f) & 0xFFFF); ++ } ++ ++ private static float lookup(int index) { ++ // A special case... Is there some way to eliminate this? ++ if (index == 32768) { ++ return SINE_TABLE_MIDPOINT; ++ } ++ ++ // Trigonometric identity: sin(-x) = -sin(x) ++ // Given a domain of 0 <= x <= 2*pi, just negate the value if x > pi. ++ // This allows the sin table size to be halved. ++ int neg = (index & 0x8000) << 16; ++ ++ // All bits set if (pi/2 <= x), none set otherwise ++ // Extracts the 15th bit from 'half' ++ int mask = (index << 17) >> 31; ++ ++ // Trigonometric identity: sin(x) = sin(pi/2 - x) ++ int pos = (0x8001 & mask) + (index ^ mask); ++ ++ // Wrap the position in the table. Moving this down to immediately before the array access ++ // seems to help the Hotspot compiler optimize the bit math better. ++ pos &= 0x7fff; ++ ++ // Fetch the corresponding value from the LUT and invert the sign bit as needed ++ // This directly manipulate the sign bit on the float bits to simplify logic ++ return Float.intBitsToFloat(SINE_TABLE_INT[pos] ^ neg); ++ } ++} +\ No newline at end of file diff --git a/patches/server/0139-Lithium-IterateOutwardsCache.patch b/patches/server/0139-Lithium-IterateOutwardsCache.patch new file mode 100644 index 00000000..47b9acc4 --- /dev/null +++ b/patches/server/0139-Lithium-IterateOutwardsCache.patch @@ -0,0 +1,161 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Fri, 8 Nov 2024 00:06:34 +0100 +Subject: [PATCH] Lithium-IterateOutwardsCache + + +diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java +index a64e5997b94cc8173f0512d1e282355f14f098ec..fa50105b9e8318d4064cdfad8b812fce40c90a8c 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.cache.IterateOutwardsCache ITERATE_OUTWARDS_CACHE = new org.dreeam.leaf.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 withinManhattan(BlockPos center, int rangeX, int rangeY, int rangeZ) { ++ // JettPack start - lithium: cached iterate outwards ++ if (center != org.dreeam.leaf.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.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/cache/IterateOutwardsCache.java b/src/main/java/org/dreeam/leaf/cache/IterateOutwardsCache.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5f75a2de67d7f557863abd9986c89a3da3406e19 +--- /dev/null ++++ b/src/main/java/org/dreeam/leaf/cache/IterateOutwardsCache.java +@@ -0,0 +1,71 @@ ++package org.dreeam.leaf.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 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 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/cache/LongList2BlockPosMutableIterable.java b/src/main/java/org/dreeam/leaf/cache/LongList2BlockPosMutableIterable.java +new file mode 100644 +index 0000000000000000000000000000000000000000..5ae1766d4e7affbc861960bee001d5577eeaa48a +--- /dev/null ++++ b/src/main/java/org/dreeam/leaf/cache/LongList2BlockPosMutableIterable.java +@@ -0,0 +1,46 @@ ++package org.dreeam.leaf.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 { ++ ++ 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 iterator() { ++ return new Iterator() { ++ ++ 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 diff --git a/patches/server/0140-Lithium-HashedList.patch b/patches/server/0140-Lithium-HashedList.patch new file mode 100644 index 00000000..9e609f20 --- /dev/null +++ b/patches/server/0140-Lithium-HashedList.patch @@ -0,0 +1,308 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Fri, 8 Nov 2024 00:14:03 +0100 +Subject: [PATCH] Lithium-HashedList + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index a40aec3a8adf39a94d62b776e845cfc193084bbb..0bf7ecc7fd0e349bd26351fa3f35ef8a3c93839d 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -114,9 +114,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + public static final int TICKS_PER_DAY = 24000; + public static final int MAX_ENTITY_SPAWN_Y = 20000000; + public static final int MIN_ENTITY_SPAWN_Y = -20000000; +- public final List blockEntityTickers = Lists.newArrayList(); // Paper - public ++ public final List blockEntityTickers = org.dreeam.leaf.hashedlist.HashedList.wrapper(Lists.newArrayList()); // Paper - public // Jettpack - lithium: hashed_list + protected final NeighborUpdater neighborUpdater; +- private final List pendingBlockEntityTickers = Lists.newArrayList(); ++ private final List pendingBlockEntityTickers = org.dreeam.leaf.hashedlist.HashedList.wrapper(Lists.newArrayList()); // Jettpack - lithium: hashed_list + private boolean tickingBlockEntities; + public final Thread thread; + private final boolean isDebug; +diff --git a/src/main/java/org/dreeam/leaf/hashedlist/HashedList.java b/src/main/java/org/dreeam/leaf/hashedlist/HashedList.java +new file mode 100644 +index 0000000000000000000000000000000000000000..bba89360de0b572516df60548d699e0f5b925121 +--- /dev/null ++++ b/src/main/java/org/dreeam/leaf/hashedlist/HashedList.java +@@ -0,0 +1,280 @@ ++package org.dreeam.leaf.hashedlist; ++ ++import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; ++import it.unimi.dsi.fastutil.objects.ReferenceArrayList; ++import java.util.Collection; ++import java.util.Iterator; ++import java.util.List; ++import java.util.ListIterator; ++import java.util.NoSuchElementException; ++ ++/** ++ * Wraps a {@link List} with a hash table which provides O(1) lookups for {@link Collection#contains(Object)}. The type ++ * contained by this list must use reference-equality semantics. ++ */ ++@SuppressWarnings("SuspiciousMethodCalls") ++public class HashedList implements List { ++ private final ReferenceArrayList list; ++ private final Reference2IntOpenHashMap counter; ++ ++ public HashedList(List list) { ++ this.list = new ReferenceArrayList<>(); ++ this.list.addAll(list); ++ ++ this.counter = new Reference2IntOpenHashMap<>(); ++ this.counter.defaultReturnValue(0); ++ ++ for (T obj : this.list) { ++ this.counter.addTo(obj, 1); ++ } ++ } ++ ++ @Override ++ public int size() { ++ return this.list.size(); ++ } ++ ++ @Override ++ public boolean isEmpty() { ++ return this.list.isEmpty(); ++ } ++ ++ @Override ++ public boolean contains(Object o) { ++ return this.counter.containsKey(o); ++ } ++ ++ @Override ++ public Iterator iterator() { ++ return this.listIterator(); ++ } ++ ++ @Override ++ public Object[] toArray() { ++ return this.list.toArray(); ++ } ++ ++ @SuppressWarnings("SuspiciousToArrayCall") ++ @Override ++ public T1[] toArray(T1[] a) { ++ return this.list.toArray(a); ++ } ++ ++ @Override ++ public boolean add(T t) { ++ this.trackReferenceAdded(t); ++ ++ return this.list.add(t); ++ } ++ ++ @Override ++ public boolean remove(Object o) { ++ this.trackReferenceRemoved(o); ++ ++ return this.list.remove(o); ++ } ++ ++ @Override ++ public boolean containsAll(Collection c) { ++ for (Object obj : c) { ++ if (!this.counter.containsKey(obj)) { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ ++ @Override ++ public boolean addAll(Collection c) { ++ for (T obj : c) { ++ this.trackReferenceAdded(obj); ++ } ++ ++ return this.list.addAll(c); ++ } ++ ++ @Override ++ public boolean addAll(int index, Collection c) { ++ for (T obj : c) { ++ this.trackReferenceAdded(obj); ++ } ++ ++ return this.list.addAll(index, c); ++ } ++ ++ @Override ++ public boolean removeAll(Collection c) { ++ for (Object obj : c) { ++ this.trackReferenceRemoved(obj); ++ } ++ ++ return this.list.removeAll(c); ++ } ++ ++ @Override ++ public boolean retainAll(Collection c) { ++ return this.list.retainAll(c); ++ } ++ ++ @Override ++ public void clear() { ++ this.counter.clear(); ++ this.list.clear(); ++ } ++ ++ @Override ++ public T get(int index) { ++ return this.list.get(index); ++ } ++ ++ @Override ++ public T set(int index, T element) { ++ T prev = this.list.set(index, element); ++ ++ if (prev != element) { ++ if (prev != null) { ++ this.trackReferenceRemoved(prev); ++ } ++ ++ this.trackReferenceAdded(element); ++ } ++ ++ return prev; ++ } ++ ++ @Override ++ public void add(int index, T element) { ++ this.trackReferenceAdded(element); ++ ++ this.list.add(index, element); ++ } ++ ++ @Override ++ public T remove(int index) { ++ T prev = this.list.remove(index); ++ ++ if (prev != null) { ++ this.trackReferenceRemoved(prev); ++ } ++ ++ return prev; ++ } ++ ++ @Override ++ public int indexOf(Object o) { ++ return this.list.indexOf(o); ++ } ++ ++ @Override ++ public int lastIndexOf(Object o) { ++ return this.list.lastIndexOf(o); ++ } ++ ++ @Override ++ public ListIterator listIterator() { ++ return this.listIterator(0); ++ } ++ ++ @Override ++ public ListIterator listIterator(int index) { ++ return new ListIterator() { ++ private final ListIterator inner = HashedList.this.list.listIterator(index); ++ ++ @Override ++ public boolean hasNext() { ++ return this.inner.hasNext(); ++ } ++ ++ @Override ++ public T next() { ++ return this.inner.next(); ++ } ++ ++ @Override ++ public boolean hasPrevious() { ++ return this.inner.hasPrevious(); ++ } ++ ++ @Override ++ public T previous() { ++ return this.inner.previous(); ++ } ++ ++ @Override ++ public int nextIndex() { ++ return this.inner.nextIndex(); ++ } ++ ++ @Override ++ public int previousIndex() { ++ return this.inner.previousIndex(); ++ } ++ ++ @Override ++ public void remove() { ++ int last = this.previousIndex(); ++ ++ if (last == -1) { ++ throw new NoSuchElementException(); ++ } ++ ++ T prev = HashedList.this.get(last); ++ ++ if (prev != null) { ++ HashedList.this.trackReferenceRemoved(prev); ++ } ++ ++ this.inner.remove(); ++ } ++ ++ @Override ++ public void set(T t) { ++ int last = this.previousIndex(); ++ ++ if (last == -1) { ++ throw new NoSuchElementException(); ++ } ++ ++ T prev = HashedList.this.get(last); ++ ++ if (prev != t) { ++ if (prev != null) { ++ HashedList.this.trackReferenceRemoved(prev); ++ } ++ ++ HashedList.this.trackReferenceAdded(t); ++ } ++ ++ this.inner.remove(); ++ } ++ ++ @Override ++ public void add(T t) { ++ HashedList.this.trackReferenceAdded(t); ++ ++ this.inner.add(t); ++ } ++ }; ++ } ++ ++ @Override ++ public List subList(int fromIndex, int toIndex) { ++ return this.list.subList(fromIndex, toIndex); ++ } ++ ++ private void trackReferenceAdded(T t) { ++ this.counter.addTo(t, 1); ++ } ++ ++ @SuppressWarnings("unchecked") ++ private void trackReferenceRemoved(Object o) { ++ if (this.counter.addTo((T) o, -1) <= 1) { ++ this.counter.removeInt(o); ++ } ++ } ++ ++ public static HashedList wrapper(List list) { ++ return new HashedList<>(list); ++ } ++} diff --git a/patches/server/0141-Use-MCUtil.asyncExecutor-for-MAIN_WORKER_EXECUTOR.patch b/patches/server/0141-Use-MCUtil.asyncExecutor-for-MAIN_WORKER_EXECUTOR.patch new file mode 100644 index 00000000..c748ec8b --- /dev/null +++ b/patches/server/0141-Use-MCUtil.asyncExecutor-for-MAIN_WORKER_EXECUTOR.patch @@ -0,0 +1,89 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Fri, 8 Nov 2024 00:54:42 +0100 +Subject: [PATCH] Use-MCUtil.asyncExecutor-for-MAIN_WORKER_EXECUTOR- + + +diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java +index 815253d03b85a7a476c1efdeca9496fd64afc137..dc0ea2e4f8ea41c96633a59243e0d8862ba28ec9 100644 +--- a/src/main/java/net/minecraft/Util.java ++++ b/src/main/java/net/minecraft/Util.java +@@ -179,7 +179,46 @@ public class Util { + if (i <= 0) { + executorService = MoreExecutors.newDirectExecutorService(); + } else { +- executorService = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue<>(), target -> new io.papermc.paper.util.ServerWorkerThread(target, s, priorityModifier)); ++ //executorService = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue<>(), target -> new io.papermc.paper.util.ServerWorkerThread(target, s, priorityModifier)); ++ // JettPack start ++ executorService = Integer.getInteger("Paper.WorkerThreadCount", i) <= 0 ? MoreExecutors.newDirectExecutorService() : new java.util.concurrent.AbstractExecutorService(){ ++ private volatile boolean shutdown = false; ++ ++ @Override ++ public final List shutdownNow() { ++ this.shutdown = true; ++ return java.util.Collections.emptyList(); ++ } ++ ++ @Override ++ public final void shutdown() { ++ this.shutdown = true; ++ } ++ ++ @Override ++ public final boolean isShutdown() { ++ return this.shutdown; ++ } ++ ++ @Override ++ public final boolean isTerminated() { ++ return this.shutdown; ++ } ++ ++ @Override ++ public final boolean awaitTermination(long l2, TimeUnit timeUnit) throws InterruptedException { ++ if (!this.shutdown) { ++ throw new UnsupportedOperationException(); ++ } ++ return true; ++ } ++ ++ @Override ++ public final void execute(Runnable runnable) { ++ io.papermc.paper.util.MCUtil.asyncExecutor.execute(new org.dreeam.leaf.serverworker.ServerWorkerWrapper(runnable)); ++ } ++ }; ++ // JettPack end + } + /* + @Override +diff --git a/src/main/java/org/dreeam/leaf/serverworker/ServerWorkerWrapper.java b/src/main/java/org/dreeam/leaf/serverworker/ServerWorkerWrapper.java +new file mode 100644 +index 0000000000000000000000000000000000000000..7f20910d62ee7fe4d8b756d3331218405aca2903 +--- /dev/null ++++ b/src/main/java/org/dreeam/leaf/serverworker/ServerWorkerWrapper.java +@@ -0,0 +1,24 @@ ++package org.dreeam.leaf.serverworker; ++ ++import com.google.common.base.Preconditions; ++import net.minecraft.Util; ++ ++public final class ServerWorkerWrapper implements Runnable { ++ private final Runnable internalRunnable; ++ ++ public ServerWorkerWrapper(Runnable runnable) { ++ this.internalRunnable = Preconditions.checkNotNull(runnable, "internalRunnable"); ++ } ++ ++ @Override ++ public final void run() { ++ try { ++ this.internalRunnable.run(); ++ return; ++ } ++ catch (Throwable throwable) { ++ Util.onThreadException(Thread.currentThread(), throwable); ++ return; ++ } ++ } ++} +\ No newline at end of file diff --git a/patches/server/0142-Fix-tick-function-tag-running-before-load.patch b/patches/server/0142-Fix-tick-function-tag-running-before-load.patch new file mode 100644 index 00000000..230c51ea --- /dev/null +++ b/patches/server/0142-Fix-tick-function-tag-running-before-load.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Fri, 8 Nov 2024 03:50:16 +0100 +Subject: [PATCH] Fix-tick-function-tag-running-before-load + + +diff --git a/src/main/java/net/minecraft/server/ServerFunctionManager.java b/src/main/java/net/minecraft/server/ServerFunctionManager.java +index f9f893a286147c9a8e49f78891381227380a2a14..b7a58ac8db0d6969155710bca162826a5ed0b6ce 100644 +--- a/src/main/java/net/minecraft/server/ServerFunctionManager.java ++++ b/src/main/java/net/minecraft/server/ServerFunctionManager.java +@@ -47,7 +47,7 @@ public class ServerFunctionManager { + this.executeTagFunctions(collection, ServerFunctionManager.LOAD_FUNCTION_TAG); + } + +- this.executeTagFunctions(this.ticking, ServerFunctionManager.TICK_FUNCTION_TAG); ++ //this.executeTagFunctions(this.ticking, ServerFunctionManager.TICK_FUNCTION_TAG); + } + } + +@@ -74,6 +74,7 @@ public class ServerFunctionManager { + } catch (Exception exception) { + ServerFunctionManager.LOGGER.warn("Failed to execute function {}", function.id(), exception); + } ++ this.executeTagFunctions(this.ticking, ServerFunctionManager.TICK_FUNCTION_TAG); // Mirai - fix tick function tag running before load + + } + diff --git a/patches/server/0143-Better-inline-world-height.patch b/patches/server/0143-Better-inline-world-height.patch new file mode 100644 index 00000000..ba37f474 --- /dev/null +++ b/patches/server/0143-Better-inline-world-height.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Fri, 8 Nov 2024 04:07:25 +0100 +Subject: [PATCH] Better-inline-world-height + + +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0bf7ecc7fd0e349bd26351fa3f35ef8a3c93839d..57cced0bb6c9541e57b10cdf0861e3beed67d88b 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -731,11 +731,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + + // Gale start - Airplane - inline level height + private final int minBuildHeight, levelHeightAccessorMinSection, height, maxBuildHeight, levelHeightAccessorMaxSection; +- @Override public final int getMaxBuildHeight() { return this.maxBuildHeight; } +- @Override public final int getMinSection() { return this.levelHeightAccessorMinSection; } +- @Override public final int getMaxSection() { return this.levelHeightAccessorMaxSection; } +- @Override public final int getMinBuildHeight() { return this.minBuildHeight; } +- @Override public final int getHeight() { return this.height; } ++ @Override public final int getMaxBuildHeight() { return maxBuildHeight; } ++ @Override public final int getMinSection() { return levelHeightAccessorMinSection; } ++ @Override public final int getMaxSection() { return levelHeightAccessorMaxSection; } ++ @Override public final int getMinBuildHeight() { return minBuildHeight; } ++ @Override public final int getHeight() { return height; } + // Gale end - Airplane - inline level height + + protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.function.Function galeWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - create paper world config & Anti-Xray // Gale - Gale configuration // Gale - Purpur - remove vanilla profiler +@@ -759,13 +759,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl + this.dimensionTypeRegistration = holder; + final DimensionType dimensionmanager = (DimensionType) holder.value(); + +- // Gale start - Airplane - inline level height +- this.minBuildHeight = LevelAccessor.super.getMinBuildHeight(); +- this.levelHeightAccessorMinSection = LevelAccessor.super.getMinSection(); +- this.height = LevelAccessor.super.getHeight(); +- this.maxBuildHeight = LevelAccessor.super.getMaxBuildHeight(); +- this.levelHeightAccessorMaxSection = LevelAccessor.super.getMaxSection(); +- // Gale end - Airplane - inline level height ++ // Gale start - Airplane - Pluto - inline level height ++ this.minBuildHeight = dimensionmanager.minY(); ++ this.levelHeightAccessorMinSection = SectionPos.blockToSectionCoord(dimensionmanager.minY()); ++ this.height = dimensionmanager.height(); ++ this.maxBuildHeight = dimensionmanager.minY() + dimensionmanager.height(); ++ this.levelHeightAccessorMaxSection = SectionPos.blockToSectionCoord((dimensionmanager.minY() + dimensionmanager.height()) - 1) + 1; ++ // Gale end - Airplane - Pluto - inline level height + this.dimension = resourcekey; + this.isClientSide = flag; + if (dimensionmanager.coordinateScale() != 1.0D) { diff --git a/patches/server/0144-branchless-clamp-logic.patch b/patches/server/0144-branchless-clamp-logic.patch new file mode 100644 index 00000000..8e57307d --- /dev/null +++ b/patches/server/0144-branchless-clamp-logic.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Taiyou06 +Date: Fri, 8 Nov 2024 04:32:35 +0100 +Subject: [PATCH] branchless-clamp-logic + + +diff --git a/src/main/java/net/minecraft/util/Mth.java b/src/main/java/net/minecraft/util/Mth.java +index ac359e7237ff6256045ee47ca287d9315900dc0e..dd79fd5331f706eb440ce96c4061ae434017967e 100644 +--- a/src/main/java/net/minecraft/util/Mth.java ++++ b/src/main/java/net/minecraft/util/Mth.java +@@ -87,7 +87,10 @@ public class Mth { + } + + public static int clamp(int value, int min, int max) { +- return Math.min(Math.max(value, min), max); ++ // First clamp to min - Leaf ++ value = value < min ? min : value; ++ // Then clamp to max - Leaf ++ return value > max ? max : value; + } + + public static long clamp(long value, long min, long max) {