diff --git a/patches/server/0001-Mirai-Branding-Changes.patch b/patches/server/0001-Mirai-Branding-Changes.patch index 258d885..1c319ef 100644 --- a/patches/server/0001-Mirai-Branding-Changes.patch +++ b/patches/server/0001-Mirai-Branding-Changes.patch @@ -217,7 +217,7 @@ index b0390eedb507d27426d1e1d73bd4ab63aec89ebe..509a9a5326d94200ca3d7a83ae47c6bb .completer(new ConsoleCommandCompleter(this.server)) .option(LineReader.Option.COMPLETE_IN_WORD, true); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 06d31a03ec7d049649e94d013429d2197b697545..02d3584994027d8cfd3c3c70a878404fe6f5fc76 100644 +index 92f685b1b6015cdd3e6c50fd39a79e2ad187fc91..9b64602e5ce5100dd1d467d404b4a6486ccc2faa 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -913,7 +913,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop optionspec11 = optionparser.accepts("port").withRequiredArg().ofType(Integer.class).defaultsTo(-1, new Integer[0]); OptionSpec optionspec12 = optionparser.accepts("serverId").withRequiredArg(); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 02d3584994027d8cfd3c3c70a878404fe6f5fc76..5b49126a64ea70ea4536a8e511f86f114d5fac1c 100644 +index 9b64602e5ce5100dd1d467d404b4a6486ccc2faa..e5e88728d2d3b4ac9e266294999af84aee4aeae4 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1373,8 +1373,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info @@ -338,7 +338,7 @@ index d18b82f1f66cd10250a12222dfb983ef57629738..176eb38372b35938c7ff9e1e91ad0eb4 } } else { if (elapsedTime >= 15000L) { // 15 seconds -@@ -879,13 +879,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -882,13 +882,13 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel()); // Paper - run this async // CraftBukkit start if (this.chatSpamTickCount.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.tabSpamLimit && !this.server.getPlayerList().isOp(this.player.getGameProfile())) { // Paper start - split and make configurable @@ -354,7 +354,7 @@ index d18b82f1f66cd10250a12222dfb983ef57629738..176eb38372b35938c7ff9e1e91ad0eb4 return; } // Paper end -@@ -3396,7 +3396,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3404,7 +3404,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic // Paper start if (!org.bukkit.Bukkit.isPrimaryThread()) { if (recipeSpamPackets.addAndGet(io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamIncrement) > io.papermc.paper.configuration.GlobalConfiguration.get().spamLimiter.recipeSpamLimit) { diff --git a/patches/server/0009-Add-last-tick-time-API.patch b/patches/server/0009-Add-last-tick-time-API.patch index 1893bfc..47fae3d 100644 --- a/patches/server/0009-Add-last-tick-time-API.patch +++ b/patches/server/0009-Add-last-tick-time-API.patch @@ -7,10 +7,10 @@ Original code by YatopiaMC, licensed under MIT You can find the original code on https://github.com/YatopiaMC/Yatopia diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 5b49126a64ea70ea4536a8e511f86f114d5fac1c..93ca26908310dca94f063c1820d96b99aa9557a6 100644 +index e5e88728d2d3b4ac9e266294999af84aee4aeae4..98b9b07e24b50e7021546680baf2ddd86ce5bd98 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1121,6 +1121,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected ServerGamePacketListenerImpl.LOGGER.warn("{} was kicked due to keepalive timeout!", this.player.getScoreboardName()); // more info -@@ -3596,6 +3612,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -3604,6 +3620,16 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic @Override public void handleKeepAlive(ServerboundKeepAlivePacket packet) { diff --git a/patches/server/0038-Logger-settings-suppressing-pointless-logs.patch b/patches/server/0038-Logger-settings-suppressing-pointless-logs.patch index 42e6d95..1a1147c 100644 --- a/patches/server/0038-Logger-settings-suppressing-pointless-logs.patch +++ b/patches/server/0038-Logger-settings-suppressing-pointless-logs.patch @@ -33,10 +33,10 @@ index 80c1e0e47818486a68e0114b063395290365346b..1194c501a82e0e84d961d4ccb62f0c60 hasSetFarWarned = true; if (this.getServer() != null && this.getServer().isDebugging()) { diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 1b563829545aebfb1b8f3cea6fa7f99e52a247cc..bc3f0dfe075ea2aeae48df05c66c9045810f7a0b 100644 +index c3d10b9eaa461f1887785cf47130631b4612b465..58fe8b248f4893cce951931ae8ce447426c4b4b4 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -2625,7 +2625,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic +@@ -2628,7 +2628,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Tic } if (playerchatmessage.hasExpiredServer(Instant.now())) { diff --git a/patches/server/0039-Add-5-second-tps-average-in-tps.patch b/patches/server/0039-Add-5-second-tps-average-in-tps.patch index fe24353..6ca8758 100644 --- a/patches/server/0039-Add-5-second-tps-average-in-tps.patch +++ b/patches/server/0039-Add-5-second-tps-average-in-tps.patch @@ -29,7 +29,7 @@ index fa56cd09102a89692b42f1d14257990508c5c720..f9251183df72ddc56662fd3f02acf216 setListData(vector); } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 7c0767c12cf01c71db982034e74cf5543ef25997..2a5bd17084238d8073d2f891f4c1af04d33fd09d 100644 +index 3cb82a09ff2d588535b60c64bb787e849346e688..5e8a2cd78380727969c771eafa745550f3c5f237 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -290,7 +290,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Mon, 10 Jan 2022 15:27:58 -0500 -Subject: [PATCH] lithium: chunk.serialization - -Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0 -You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) - -diff --git a/src/main/java/me/jellysquid/mods/lithium/common/world/chunk/LithiumHashPalette.java b/src/main/java/me/jellysquid/mods/lithium/common/world/chunk/LithiumHashPalette.java -new file mode 100644 -index 0000000000000000000000000000000000000000..16debe176798f316c122e8e7aef2b50ecb9883a6 ---- /dev/null -+++ b/src/main/java/me/jellysquid/mods/lithium/common/world/chunk/LithiumHashPalette.java -@@ -0,0 +1,189 @@ -+package me.jellysquid.mods.lithium.common.world.chunk; -+ -+import com.google.common.collect.ImmutableList; -+import it.unimi.dsi.fastutil.HashCommon; -+import it.unimi.dsi.fastutil.objects.Reference2IntMap; -+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; -+import java.util.Arrays; -+import java.util.List; -+import java.util.function.Predicate; -+import net.minecraft.core.IdMap; -+import net.minecraft.network.FriendlyByteBuf; -+import net.minecraft.world.level.chunk.Palette; -+import net.minecraft.world.level.chunk.PaletteResize; -+ -+import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR; -+ -+/** -+ * Generally provides better performance over the vanilla {@link net.minecraft.world.level.chunk.HashMapPalette} when calling -+ * {@link LithiumHashPalette#idFor(Object)} through using a faster backing map and reducing pointer chasing. -+ */ -+public class LithiumHashPalette implements Palette { -+ private static final int ABSENT_VALUE = -1; -+ -+ private final IdMap idList; -+ private final PaletteResize resizeHandler; -+ private final int indexBits; -+ -+ private final Reference2IntMap table; -+ private T[] entries; -+ private int size = 0; -+ -+ public LithiumHashPalette(IdMap idList, PaletteResize resizeHandler, int indexBits, T[] entries, Reference2IntMap table, int size) { -+ this.idList = idList; -+ this.resizeHandler = resizeHandler; -+ this.indexBits = indexBits; -+ this.entries = entries; -+ this.table = table; -+ this.size = size; -+ } -+ -+ public LithiumHashPalette(IdMap idList, int bits, PaletteResize resizeHandler, List list) { -+ this(idList, bits, resizeHandler); -+ -+ for (T t : list) { -+ this.addEntry(t); -+ } -+ } -+ -+ @SuppressWarnings("unchecked") -+ public LithiumHashPalette(IdMap idList, int bits, PaletteResize resizeHandler) { -+ this.idList = idList; -+ this.indexBits = bits; -+ this.resizeHandler = resizeHandler; -+ -+ int capacity = 1 << bits; -+ -+ this.entries = (T[]) new Object[capacity]; -+ this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR); -+ this.table.defaultReturnValue(ABSENT_VALUE); -+ } -+ -+ @Override -+ public int idFor(T obj) { -+ int id = this.table.getInt(obj); -+ -+ if (id == ABSENT_VALUE) { -+ id = this.computeEntry(obj); -+ } -+ -+ return id; -+ } -+ -+ @Override -+ public boolean maybeHas(Predicate predicate) { -+ for (int i = 0; i < this.size; ++i) { -+ if (predicate.test(this.entries[i])) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ -+ private int computeEntry(T obj) { -+ int id = this.addEntry(obj); -+ -+ if (id >= 1 << this.indexBits) { -+ if (this.resizeHandler == null) { -+ throw new IllegalStateException("Cannot grow"); -+ } else { -+ id = this.resizeHandler.onResize(this.indexBits + 1, obj); -+ } -+ } -+ -+ return id; -+ } -+ -+ private int addEntry(T obj) { -+ int nextId = this.size; -+ -+ if (nextId >= this.entries.length) { -+ this.resize(this.size); -+ } -+ -+ this.table.put(obj, nextId); -+ this.entries[nextId] = obj; -+ -+ this.size++; -+ -+ return nextId; -+ } -+ -+ private void resize(int neededCapacity) { -+ this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1)); -+ } -+ -+ @Override -+ public T valueFor(int id) { -+ T[] entries = this.entries; -+ -+ if (id >= 0 && id < entries.length) { -+ return entries[id]; -+ } -+ -+ return null; -+ } -+ -+ @Override -+ public void read(FriendlyByteBuf buf) { -+ this.clear(); -+ -+ int entryCount = buf.readVarInt(); -+ -+ for (int i = 0; i < entryCount; ++i) { -+ this.addEntry(this.idList.byId(buf.readVarInt())); -+ } -+ } -+ -+ @Override -+ public void write(FriendlyByteBuf buf) { -+ int size = this.size; -+ buf.writeVarInt(size); -+ -+ for (int i = 0; i < size; ++i) { -+ buf.writeVarInt(this.idList.getId(this.valueFor(i))); -+ } -+ } -+ -+ @Override -+ public int getSerializedSize() { -+ int size = FriendlyByteBuf.getVarIntSize(this.size); -+ -+ for (int i = 0; i < this.size; ++i) { -+ size += FriendlyByteBuf.getVarIntSize(this.idList.getId(this.valueFor(i))); -+ } -+ -+ return size; -+ } -+ -+ @Override -+ public int getSize() { -+ return this.size; -+ } -+ -+ @Override -+ public Palette copy() { -+ return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size); -+ } -+ -+ private void clear() { -+ Arrays.fill(this.entries, null); -+ this.table.clear(); -+ this.size = 0; -+ } -+ -+ public List getElements() { -+ ImmutableList.Builder builder = new ImmutableList.Builder<>(); -+ for (T entry : this.entries) { -+ if (entry != null) { -+ builder.add(entry); -+ } -+ } -+ return builder.build(); -+ } -+ -+ public static Palette create(int bits, IdMap idList, PaletteResize listener, List list) { -+ return new LithiumHashPalette<>(idList, bits, listener, list); -+ } -+} -\ No newline at end of file -diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java -index 106610ccc74b70b557b01c61262d56c4f1147acf..fc986f02290fbe20246022072944980f35dd200c 100644 ---- a/src/main/java/net/minecraft/util/BitStorage.java -+++ b/src/main/java/net/minecraft/util/BitStorage.java -@@ -1,6 +1,7 @@ - package net.minecraft.util; - - import java.util.function.IntConsumer; -+import net.minecraft.world.level.chunk.Palette; // JettPack - - public interface BitStorage { - int getAndSet(int index, int value); -@@ -31,4 +32,6 @@ public interface BitStorage { - - } - // Paper end -+ -+ void compact(Palette srcPalette, Palette dstPalette, short[] out); // JettPack - lithium: chunk.serialization - } -diff --git a/src/main/java/net/minecraft/util/SimpleBitStorage.java b/src/main/java/net/minecraft/util/SimpleBitStorage.java -index 36e33923bf48e56c743ed043bcbc66bc32f0422f..0272dee738e86e066108f5cc3729136335d8197e 100644 ---- a/src/main/java/net/minecraft/util/SimpleBitStorage.java -+++ b/src/main/java/net/minecraft/util/SimpleBitStorage.java -@@ -2,6 +2,7 @@ package net.minecraft.util; - - import java.util.function.IntConsumer; - import javax.annotation.Nullable; -+import net.minecraft.world.level.chunk.Palette; // JettPack - import org.apache.commons.lang3.Validate; - - public class SimpleBitStorage implements BitStorage { -@@ -201,4 +202,44 @@ public class SimpleBitStorage implements BitStorage { - super(message); - } - } -+ -+ // JettPack start - lithium: chunk.serialization -+ @Override -+ public void compact(Palette srcPalette, Palette dstPalette, short[] out) { -+ if (this.size >= Short.MAX_VALUE) { -+ throw new IllegalStateException("Array too large"); -+ } -+ -+ if (this.size != out.length) { -+ throw new IllegalStateException("Array size mismatch"); -+ } -+ -+ short[] mappings = new short[(int) (this.mask + 1)]; -+ -+ int idx = 0; -+ -+ for (long word : this.data) { -+ long bits = word; -+ -+ for (int elementIdx = 0; elementIdx < this.valuesPerLong; ++elementIdx) { -+ int value = (int) (bits & this.mask); -+ int remappedId = mappings[value]; -+ -+ if (remappedId == 0) { -+ remappedId = dstPalette.idFor(srcPalette.valueFor(value)) + 1; -+ mappings[value] = (short) remappedId; -+ } -+ -+ out[idx] = (short) (remappedId - 1); -+ bits >>= this.bits; -+ -+ ++idx; -+ -+ if (idx >= this.size) { -+ return; -+ } -+ } -+ } -+ } -+ // JettPack end - } -diff --git a/src/main/java/net/minecraft/util/ZeroBitStorage.java b/src/main/java/net/minecraft/util/ZeroBitStorage.java -index 97c744508cc535418eba65fa722859c81c22d647..a2ea0a2864b9c4f847f1a14ffc0900e67c18f9ee 100644 ---- a/src/main/java/net/minecraft/util/ZeroBitStorage.java -+++ b/src/main/java/net/minecraft/util/ZeroBitStorage.java -@@ -2,6 +2,7 @@ package net.minecraft.util; - - import java.util.Arrays; - import java.util.function.IntConsumer; -+import net.minecraft.world.level.chunk.Palette; // JettPack - import org.apache.commons.lang3.Validate; - - public class ZeroBitStorage implements BitStorage { -@@ -72,4 +73,6 @@ public class ZeroBitStorage implements BitStorage { - public BitStorage copy() { - return this; - } -+ -+ @Override public void compact(Palette srcPalette, Palette dstPalette, short[] out) {} // JettPack - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java b/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java -index acae3eb30e0689048937f479dc3070f0688abdad..9c2b79655f2c63a208c7087d5d897db0fb23f697 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java -+++ b/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java -@@ -1,5 +1,5 @@ - package net.minecraft.world.level.chunk; - --interface PaletteResize { -+public interface PaletteResize { // JettPack - make public - int onResize(int newBits, T object); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -index 7908360dd47937b2cb702e381802b7b278a5198e..f31fd07ce34f798f54d4fae1ccfa22636d4ec2aa 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java -@@ -22,8 +22,23 @@ import net.minecraft.util.Mth; - import net.minecraft.util.SimpleBitStorage; - import net.minecraft.util.ThreadingDetector; - import net.minecraft.util.ZeroBitStorage; -+import me.jellysquid.mods.lithium.common.world.chunk.LithiumHashPalette; // JettPack - - public class PalettedContainer implements PaletteResize, PalettedContainerRO { -+ // JettPack start - lithium: chunk.serialization -+ private static final ThreadLocal CACHED_ARRAY_4096 = ThreadLocal.withInitial(() -> new short[4096]); -+ private static final ThreadLocal CACHED_ARRAY_64 = ThreadLocal.withInitial(() -> new short[64]); -+ private Optional asOptional(long[] data) { -+ return Optional.of(Arrays.stream(data)); -+ } -+ private short[] getOrCreate(int size) { -+ return switch (size) { -+ case 64 -> CACHED_ARRAY_64.get(); -+ case 4096 -> CACHED_ARRAY_4096.get(); -+ default -> new short[size]; -+ }; -+ } -+ // JettPack end - private static final int MIN_PALETTE_BITS = 0; - private final PaletteResize dummyPaletteResize = (newSize, added) -> { - return 0; -@@ -299,30 +314,54 @@ public class PalettedContainer implements PaletteResize, PalettedContainer - public synchronized PalettedContainerRO.PackedData pack(IdMap idList, PalettedContainer.Strategy paletteProvider) { // Paper - synchronize - this.acquire(); - -- PalettedContainerRO.PackedData var12; -+ // JettPack start - lithium: chunk.serialization -+ Optional data = Optional.empty(); -+ List elements = null; - try { -- HashMapPalette hashMapPalette = new HashMapPalette<>(idList, this.data.storage.getBits(), this.dummyPaletteResize); -- int i = paletteProvider.size(); -- int[] is = new int[i]; -- this.data.storage.unpack(is); -- swapPalette(is, (id) -> { -- return hashMapPalette.idFor(this.data.palette.valueFor(id)); -- }); -- int j = paletteProvider.calculateBitsForSerialization(idList, hashMapPalette.getSize()); -- Optional optional; -- if (j != 0) { -- SimpleBitStorage simpleBitStorage = new SimpleBitStorage(j, i, is); -- optional = Optional.of(Arrays.stream(simpleBitStorage.getRaw())); -- } else { -- optional = Optional.empty(); -+ // The palette that will be serialized -+ LithiumHashPalette hashPalette = null; -+ -+ final Palette palette = this.data.palette(); -+ final BitStorage storage = this.data.storage(); -+ if (storage instanceof ZeroBitStorage || palette.getSize() == 1) { -+ // If the palette only contains one entry, don't attempt to repack it. -+ elements = List.of(palette.valueFor(0)); -+ } else if (palette instanceof LithiumHashPalette lithiumHashPalette) { -+ hashPalette = lithiumHashPalette; - } - -- var12 = new PalettedContainerRO.PackedData<>(hashMapPalette.getEntries(), optional); -+ if (elements == null) { -+ LithiumHashPalette compactedPalette = new LithiumHashPalette<>(idList, storage.getBits(), this.dummyPaletteResize); -+ short[] array = this.getOrCreate(paletteProvider.size()); -+ -+ storage.compact(this.data.palette(), compactedPalette, array); -+ -+ // If the palette didn't change during compaction, do a simple copy of the data array -+ if (hashPalette != null && hashPalette.getSize() == compactedPalette.getSize() && storage.getBits() == paletteProvider.calculateBitsForSerialization(idList, hashPalette.getSize())) { // paletteSize can de-sync from palette - see https://github.com/CaffeineMC/lithium-fabric/issues/279 -+ data = this.asOptional(storage.getRaw().clone()); -+ elements = hashPalette.getElements(); -+ } else { -+ int bits = paletteProvider.calculateBitsForSerialization(idList, compactedPalette.getSize()); -+ if (bits != 0) { -+ // Re-pack the integer array as the palette has changed size -+ SimpleBitStorage copy = new SimpleBitStorage(bits, array.length); -+ for (int i = 0; i < array.length; ++i) { -+ copy.set(i, array[i]); -+ } -+ -+ // We don't need to clone the data array as we are the sole owner of it -+ data = this.asOptional(copy.getRaw()); -+ } -+ -+ elements = compactedPalette.getElements(); -+ } -+ } - } finally { - this.release(); - } - -- return var12; -+ return new PalettedContainerRO.PackedData<>(elements, data); -+ // JettPack end - } - - private static void swapPalette(int[] is, IntUnaryOperator applier) { -@@ -362,17 +401,37 @@ public class PalettedContainer implements PaletteResize, PalettedContainer - - @Override - public void count(PalettedContainer.CountConsumer counter) { -- if (this.data.palette.getSize() == 1) { -- counter.accept(this.data.palette.valueFor(0), this.data.storage.getSize()); -- } else { -- Int2IntOpenHashMap int2IntOpenHashMap = new Int2IntOpenHashMap(); -- this.data.storage.getAll((key) -> { -- int2IntOpenHashMap.addTo(key, 1); -- }); -- int2IntOpenHashMap.int2IntEntrySet().forEach((entry) -> { -- counter.accept(this.data.palette.valueFor(entry.getIntKey()), entry.getIntValue()); -- }); -+ // JettPack start - lithium: chunk.serialization -+ int len = this.data.palette().getSize(); -+ -+ // Do not allocate huge arrays if we're using a large palette -+ if (len > 4096) { -+ // VanillaCopy -+ if (this.data.palette.getSize() == 1) { -+ counter.accept(this.data.palette.valueFor(0), this.data.storage.getSize()); -+ } else { -+ Int2IntOpenHashMap int2IntOpenHashMap = new Int2IntOpenHashMap(); -+ this.data.storage.getAll((key) -> { -+ int2IntOpenHashMap.addTo(key, 1); -+ }); -+ int2IntOpenHashMap.int2IntEntrySet().forEach((entry) -> { -+ counter.accept(this.data.palette.valueFor(entry.getIntKey()), entry.getIntValue()); -+ }); -+ } -+ } -+ -+ short[] counts = new short[len]; -+ -+ this.data.storage().getAll(i -> counts[i]++); -+ -+ for (int i = 0; i < counts.length; i++) { -+ T obj = this.data.palette().valueFor(i); -+ -+ if (obj != null) { -+ counter.accept(obj, counts[i]); -+ } - } -+ // JettPack end - } - - static record Configuration(Palette.Factory factory, int bits) { diff --git a/patches/server/0068-Set-item-stuck-sleep-to-15-ticks.patch b/patches/server/0067-Set-item-stuck-sleep-to-15-ticks.patch similarity index 100% rename from patches/server/0068-Set-item-stuck-sleep-to-15-ticks.patch rename to patches/server/0067-Set-item-stuck-sleep-to-15-ticks.patch diff --git a/patches/server/0069-Smarter-statistics-ticking.patch b/patches/server/0068-Smarter-statistics-ticking.patch similarity index 100% rename from patches/server/0069-Smarter-statistics-ticking.patch rename to patches/server/0068-Smarter-statistics-ticking.patch diff --git a/patches/server/0070-some-entity-micro-opts.patch b/patches/server/0069-some-entity-micro-opts.patch similarity index 100% rename from patches/server/0070-some-entity-micro-opts.patch rename to patches/server/0069-some-entity-micro-opts.patch diff --git a/patches/server/0071-Dont-eat-blocks-in-non-ticking-chunks.patch b/patches/server/0070-Dont-eat-blocks-in-non-ticking-chunks.patch similarity index 100% rename from patches/server/0071-Dont-eat-blocks-in-non-ticking-chunks.patch rename to patches/server/0070-Dont-eat-blocks-in-non-ticking-chunks.patch diff --git a/patches/server/0072-Fast-speed-check.patch b/patches/server/0071-Fast-speed-check.patch similarity index 96% rename from patches/server/0072-Fast-speed-check.patch rename to patches/server/0071-Fast-speed-check.patch index cc986a6..9913551 100644 --- a/patches/server/0072-Fast-speed-check.patch +++ b/patches/server/0071-Fast-speed-check.patch @@ -36,7 +36,7 @@ index 6bc313aa05d572236f05d0960fde0f27b9f93d50..9bdcad2b05367a8dcb519a2db8c4efea this.setDeltaMovement(this.getDeltaMovement().multiply((double) f2, 1.0D, (double) f2)); // Paper start - remove expensive streams from here diff --git a/src/main/java/wtf/etil/mirai/MiraiConfig.java b/src/main/java/wtf/etil/mirai/MiraiConfig.java -index 7a5d000c25af93b60215b3e2867358d7c238c6e4..7658c7743646fb1d3e07a9f91245407a2dd191dd 100644 +index c12ab155bdd4a1bad7bb428ecddc20a7999f91f5..b9351994ac2b9865ca39fdb76625983cf7c63cdb 100644 --- a/src/main/java/wtf/etil/mirai/MiraiConfig.java +++ b/src/main/java/wtf/etil/mirai/MiraiConfig.java @@ -221,4 +221,11 @@ public class MiraiConfig { diff --git a/patches/server/0073-lithium-cache-iterate-outwards.patch b/patches/server/0072-lithium-cache-iterate-outwards.patch similarity index 100% rename from patches/server/0073-lithium-cache-iterate-outwards.patch rename to patches/server/0072-lithium-cache-iterate-outwards.patch diff --git a/patches/server/0074-lithium-ai.raid.patch b/patches/server/0073-lithium-ai.raid.patch similarity index 100% rename from patches/server/0074-lithium-ai.raid.patch rename to patches/server/0073-lithium-ai.raid.patch diff --git a/patches/server/0075-lithium-block.moving_block_shapes.patch b/patches/server/0074-lithium-block.moving_block_shapes.patch similarity index 100% rename from patches/server/0075-lithium-block.moving_block_shapes.patch rename to patches/server/0074-lithium-block.moving_block_shapes.patch diff --git a/patches/server/0076-lithium-shapes.blockstate_cache.patch b/patches/server/0075-lithium-shapes.blockstate_cache.patch similarity index 100% rename from patches/server/0076-lithium-shapes.blockstate_cache.patch rename to patches/server/0075-lithium-shapes.blockstate_cache.patch diff --git a/patches/server/0077-lithium-gen.patch b/patches/server/0076-lithium-gen.patch similarity index 100% rename from patches/server/0077-lithium-gen.patch rename to patches/server/0076-lithium-gen.patch diff --git a/patches/server/0078-PaperPR-Stop-large-look-changes-from-crashing-the-se.patch b/patches/server/0077-PaperPR-Stop-large-look-changes-from-crashing-the-se.patch similarity index 100% rename from patches/server/0078-PaperPR-Stop-large-look-changes-from-crashing-the-se.patch rename to patches/server/0077-PaperPR-Stop-large-look-changes-from-crashing-the-se.patch diff --git a/patches/server/0079-PaperPR-Add-more-collision-code-skipping-logic.patch b/patches/server/0078-PaperPR-Add-more-collision-code-skipping-logic.patch similarity index 100% rename from patches/server/0079-PaperPR-Add-more-collision-code-skipping-logic.patch rename to patches/server/0078-PaperPR-Add-more-collision-code-skipping-logic.patch diff --git a/patches/server/0080-vmp-use-linked-map-for-entity-trackers-for-faster-it.patch b/patches/server/0079-vmp-use-linked-map-for-entity-trackers-for-faster-it.patch similarity index 100% rename from patches/server/0080-vmp-use-linked-map-for-entity-trackers-for-faster-it.patch rename to patches/server/0079-vmp-use-linked-map-for-entity-trackers-for-faster-it.patch diff --git a/patches/server/0081-c2me-reduce_allocs.patch b/patches/server/0080-c2me-reduce_allocs.patch similarity index 100% rename from patches/server/0081-c2me-reduce_allocs.patch rename to patches/server/0080-c2me-reduce_allocs.patch diff --git a/patches/server/0082-lithium-ai.sensor.secondary_poi.patch b/patches/server/0081-lithium-ai.sensor.secondary_poi.patch similarity index 100% rename from patches/server/0082-lithium-ai.sensor.secondary_poi.patch rename to patches/server/0081-lithium-ai.sensor.secondary_poi.patch diff --git a/patches/server/0083-Fix-tick-function-tag-running-before-load.patch b/patches/server/0082-Fix-tick-function-tag-running-before-load.patch similarity index 100% rename from patches/server/0083-Fix-tick-function-tag-running-before-load.patch rename to patches/server/0082-Fix-tick-function-tag-running-before-load.patch diff --git a/patches/server/0085-Optimize-default-values-for-configs.patch b/patches/server/0083-Optimize-default-values-for-configs.patch similarity index 100% rename from patches/server/0085-Optimize-default-values-for-configs.patch rename to patches/server/0083-Optimize-default-values-for-configs.patch diff --git a/patches/server/0086-Configurable-map-update-interval.patch b/patches/server/0084-Configurable-map-update-interval.patch similarity index 96% rename from patches/server/0086-Configurable-map-update-interval.patch rename to patches/server/0084-Configurable-map-update-interval.patch index 74e249a..fe338e2 100644 --- a/patches/server/0086-Configurable-map-update-interval.patch +++ b/patches/server/0084-Configurable-map-update-interval.patch @@ -27,7 +27,7 @@ index 67b88da702b780f79c0496cb17f1e6f1f8dd6c2b..712707da510977bfa1ce4b991fd8a8f5 // CraftBukkit start java.util.Collection icons = new java.util.ArrayList(); diff --git a/src/main/java/wtf/etil/mirai/MiraiConfig.java b/src/main/java/wtf/etil/mirai/MiraiConfig.java -index 7658c7743646fb1d3e07a9f91245407a2dd191dd..23761b89a2fac069e9709db9741afa1ba24ae1d1 100644 +index b9351994ac2b9865ca39fdb76625983cf7c63cdb..65eac0889de3dd95a4b850f99b5193bede04358f 100644 --- a/src/main/java/wtf/etil/mirai/MiraiConfig.java +++ b/src/main/java/wtf/etil/mirai/MiraiConfig.java @@ -228,4 +228,11 @@ public class MiraiConfig { diff --git a/patches/server/0084-lithium-suffocation.patch b/patches/server/0084-lithium-suffocation.patch deleted file mode 100644 index e3efa09..0000000 --- a/patches/server/0084-lithium-suffocation.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: etil2jz -Date: Fri, 8 Apr 2022 22:21:48 +0200 -Subject: [PATCH] lithium: suffocation - -Author: 2No2Name <2No2Name@web.de> - -Original license: GNU Lesser General Public License v3.0 -Original project: https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) - -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 9bdcad2b05367a8dcb519a2db8c4efea94a4d21c..ae428552912f5a484ecf581b24c0e362c3e2407f 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -2593,39 +2593,64 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { - return !this.isRemoved(); - } - -+ // Mirai start - lithium: suffocation -+ /** -+ * @author 2No2Name -+ * @reason Avoid stream code, use optimized chunk section iteration order -+ */ - public boolean isInWall() { -+ // [VanillaCopy] The whole method functionality including bug below. Cannot use ChunkAwareBlockCollisionSweeper due to ignoring of oversized blocks - if (this.noPhysics) { - return false; -- } else { -- float f = this.dimensions.width * 0.8F; -- AABB axisalignedbb = AABB.ofSize(this.getEyePosition(), (double) f, 1.0E-6D, (double) f); -- -- BlockPos.MutableBlockPos blockposition = new BlockPos.MutableBlockPos(); -- int minX = Mth.floor(axisalignedbb.minX); -- int minY = Mth.floor(axisalignedbb.minY); -- int minZ = Mth.floor(axisalignedbb.minZ); -- int maxX = Mth.floor(axisalignedbb.maxX); -- int maxY = Mth.floor(axisalignedbb.maxY); -- int maxZ = Mth.floor(axisalignedbb.maxZ); -- for (int fz = minZ; fz <= maxZ; ++fz) { -- for (int fx = minX; fx <= maxX; ++fx) { -- for (int fy = minY; fy <= maxY; ++fy) { -- net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)this.level.getChunkIfLoadedImmediately(fx >> 4, fz >> 4); -- if (chunk == null) { -- continue; -+ } -+ Vec3 position = this.getEyePosition(); -+ double suffocationRadius = Math.abs((double) (this.dimensions.width * 0.8f) / 2.0); -+ -+ double suffocationMinX = position.x - suffocationRadius; -+ double suffocationMinY = position.y - 5.0E-7; -+ double suffocationMinZ = position.z - suffocationRadius; -+ double suffocationMaxX = position.x + suffocationRadius; -+ double suffocationMaxY = position.y + 5.0E-7; -+ double suffocationMaxZ = position.z + suffocationRadius; -+ int minX = Mth.floor(suffocationMinX); -+ int minY = Mth.floor(suffocationMinY); -+ int minZ = Mth.floor(suffocationMinZ); -+ int maxX = Mth.floor(suffocationMaxX); -+ int maxY = Mth.floor(suffocationMaxY); -+ int maxZ = Mth.floor(suffocationMaxZ); -+ -+ Level level = this.level; -+ //skip getting blocks when the entity is outside the world height -+ //also avoids infinite loop with entities below y = Integer.MIN_VALUE (some modded servers do that) -+ if (level.getMinBuildHeight() > maxY || level.getMaxBuildHeight() < minY) { -+ return false; -+ } -+ -+ BlockPos.MutableBlockPos blockposition = new BlockPos.MutableBlockPos(); -+ VoxelShape suffocationShape = null; -+ -+ for (int y = minY; y <= maxY; y++) { -+ for (int z = minZ; z <= maxZ; z++) { -+ for (int x = minX; x <= maxX; x++) { -+ blockposition.set(x, y, z); -+ BlockState iblockdata = level.getBlockState(blockposition); -+ if (!iblockdata.isAir() && iblockdata.isSuffocating(this.level, blockposition)) { -+ if (suffocationShape == null) { -+ suffocationShape = Shapes.create(new AABB(suffocationMinX, suffocationMinY, suffocationMinZ, suffocationMaxX, suffocationMaxY, suffocationMaxZ)); - } - -- BlockState iblockdata = chunk.getBlockStateFinal(fx, fy, fz); -- blockposition.set(fx, fy, fz); -- if (!iblockdata.isAir() && iblockdata.isSuffocating(this.level, blockposition) && Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level, blockposition).move((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()), Shapes.create(axisalignedbb), BooleanOp.AND)) { -+ if (Shapes.joinIsNotEmpty(iblockdata.getCollisionShape(this.level, blockposition). -+ move(blockposition.getX(), blockposition.getY(), blockposition.getZ()), -+ suffocationShape, BooleanOp.AND)) { - return true; - } - } - } - } -- return false; - } -+ return false; - } -+ // Mirai end - - public InteractionResult interact(Player player, InteractionHand hand) { - return InteractionResult.PASS; diff --git a/patches/server/0087-Fix-hunger-saturation-depleting-on-peaceful.patch b/patches/server/0085-Fix-hunger-saturation-depleting-on-peaceful.patch similarity index 100% rename from patches/server/0087-Fix-hunger-saturation-depleting-on-peaceful.patch rename to patches/server/0085-Fix-hunger-saturation-depleting-on-peaceful.patch diff --git a/patches/server/0088-Fix-mobs-attacking-themselves.patch b/patches/server/0086-Fix-mobs-attacking-themselves.patch similarity index 100% rename from patches/server/0088-Fix-mobs-attacking-themselves.patch rename to patches/server/0086-Fix-mobs-attacking-themselves.patch diff --git a/patches/server/0089-Fix-brewing-stands-resetting-their-brewTime-when-bei.patch b/patches/server/0087-Fix-brewing-stands-resetting-their-brewTime-when-bei.patch similarity index 100% rename from patches/server/0089-Fix-brewing-stands-resetting-their-brewTime-when-bei.patch rename to patches/server/0087-Fix-brewing-stands-resetting-their-brewTime-when-bei.patch diff --git a/patches/server/0091-Save-Json-list-asynchronously.patch b/patches/server/0088-Save-Json-list-asynchronously.patch similarity index 100% rename from patches/server/0091-Save-Json-list-asynchronously.patch rename to patches/server/0088-Save-Json-list-asynchronously.patch diff --git a/patches/server/0092-Swaps-the-predicate-order-of-collision.patch b/patches/server/0089-Swaps-the-predicate-order-of-collision.patch similarity index 93% rename from patches/server/0092-Swaps-the-predicate-order-of-collision.patch rename to patches/server/0089-Swaps-the-predicate-order-of-collision.patch index cdefd08..6d2b75b 100644 --- a/patches/server/0092-Swaps-the-predicate-order-of-collision.patch +++ b/patches/server/0089-Swaps-the-predicate-order-of-collision.patch @@ -8,7 +8,7 @@ Original license: GPLv3 Original project: https://github.com/Akarin-project/Akarin diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index ae428552912f5a484ecf581b24c0e362c3e2407f..a21f7de5331fc31a291fe177e6e1e843c7895cee 100644 +index 9bdcad2b05367a8dcb519a2db8c4efea94a4d21c..6184b54512e795877c7db9a88a0e3324b2858173 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1983,8 +1983,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { diff --git a/patches/server/0093-Fix-head-rotation-packet-spam.patch b/patches/server/0090-Fix-head-rotation-packet-spam.patch similarity index 100% rename from patches/server/0093-Fix-head-rotation-packet-spam.patch rename to patches/server/0090-Fix-head-rotation-packet-spam.patch diff --git a/patches/server/0090-lithium-world.tick_scheduler.patch b/patches/server/0090-lithium-world.tick_scheduler.patch deleted file mode 100644 index 13ccede..0000000 --- a/patches/server/0090-lithium-world.tick_scheduler.patch +++ /dev/null @@ -1,509 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Arthur Blanchot -Date: Fri, 24 Jun 2022 21:17:05 +0200 -Subject: [PATCH] lithium: world.tick_scheduler - -Original license: GPLv3 -Original project: https://github.com/CaffeineMC/lithium-fabric (Yarn mappings) - -diff --git a/src/main/java/me/jellysquid/mods/lithium/common/world/scheduler/OrderedTickQueue.java b/src/main/java/me/jellysquid/mods/lithium/common/world/scheduler/OrderedTickQueue.java -new file mode 100644 -index 0000000000000000000000000000000000000000..52e90ea09b44543af661c214767073cf9d5f3d8f ---- /dev/null -+++ b/src/main/java/me/jellysquid/mods/lithium/common/world/scheduler/OrderedTickQueue.java -@@ -0,0 +1,192 @@ -+package me.jellysquid.mods.lithium.common.world.scheduler; -+ -+import it.unimi.dsi.fastutil.HashCommon; -+import java.util.*; -+import net.minecraft.world.ticks.ScheduledTick; -+ -+/** -+ -+ */ -+public class OrderedTickQueue extends AbstractQueue> { -+ private static final int INITIAL_CAPACITY = 16; -+ private static final Comparator> COMPARATOR = Comparator.comparingLong(ScheduledTick::subTickOrder); -+ -+ private ScheduledTick[] arr; -+ -+ private int lastIndexExclusive; -+ private int firstIndex; -+ -+ private long currentMaxSubTickOrder = Long.MIN_VALUE; -+ private boolean isSorted; -+ private ScheduledTick unsortedPeekResult; -+ -+ @SuppressWarnings("unchecked") -+ public OrderedTickQueue(int capacity) { -+ this.arr = (ScheduledTick[]) new ScheduledTick[capacity]; -+ this.lastIndexExclusive = 0; -+ this.isSorted = true; -+ this.unsortedPeekResult = null; -+ this.firstIndex = 0; -+ } -+ -+ public OrderedTickQueue() { -+ this(INITIAL_CAPACITY); -+ } -+ -+ @Override -+ public void clear() { -+ Arrays.fill(this.arr, null); -+ this.lastIndexExclusive = 0; -+ this.firstIndex = 0; -+ this.currentMaxSubTickOrder = Long.MIN_VALUE; -+ this.isSorted = true; -+ this.unsortedPeekResult = null; -+ } -+ -+ @Override -+ public Iterator> iterator() { -+ if (this.isEmpty()) { -+ return Collections.emptyIterator(); -+ } -+ this.sort(); -+ return new Iterator<>() { -+ int nextIndex = OrderedTickQueue.this.firstIndex; -+ -+ @Override -+ public boolean hasNext() { -+ return this.nextIndex < OrderedTickQueue.this.lastIndexExclusive; -+ } -+ -+ @Override -+ public ScheduledTick next() { -+ return OrderedTickQueue.this.arr[this.nextIndex++]; -+ } -+ }; -+ } -+ -+ @Override -+ public ScheduledTick poll() { -+ if (this.isEmpty()) { -+ return null; -+ } -+ if (!this.isSorted) { -+ this.sort(); -+ } -+ ScheduledTick nextTick; -+ int polledIndex = this.firstIndex++; -+ ScheduledTick[] ticks = this.arr; -+ nextTick = ticks[polledIndex]; -+ ticks[polledIndex] = null; -+ return nextTick; -+ } -+ -+ @Override -+ public ScheduledTick peek() { -+ if (!this.isSorted) { -+ return this.unsortedPeekResult; -+ } else if (this.lastIndexExclusive > this.firstIndex) { -+ return this.getTickAtIndex(this.firstIndex); -+ } -+ return null; -+ } -+ -+ public boolean offer(ScheduledTick tick) { -+ if (this.lastIndexExclusive >= this.arr.length) { -+ //todo remove consumed elements first -+ this.arr = copyArray(this.arr, HashCommon.nextPowerOfTwo(this.arr.length + 1)); -+ } -+ if (tick.subTickOrder() <= this.currentMaxSubTickOrder) { -+ //Set to unsorted instead of slowing down the insertion -+ //This is rare but may happen in bulk -+ //Sorting later needs O(n*log(n)) time, but it only needs to happen when unordered insertion needs to happen -+ //Therefore it is better than n times log(n) time of the PriorityQueue that happens on ordered insertion too -+ this.isSorted = false; -+ ScheduledTick firstTick = this.size() > 0 ? this.arr[this.firstIndex] : null; -+ this.unsortedPeekResult = firstTick == null || tick.subTickOrder() < firstTick.subTickOrder() ? tick : firstTick; -+ } else { -+ this.currentMaxSubTickOrder = tick.subTickOrder(); -+ } -+ this.arr[this.lastIndexExclusive++] = tick; -+ return true; -+ } -+ -+ public int size() { -+ return this.lastIndexExclusive - this.firstIndex; -+ } -+ -+ private void resize(int size) { -+ // Only compact the array if it is completely empty or is less than 50% filled -+ if (size == 0 || size < this.arr.length / 2) { -+ this.arr = copyArray(this.arr, size); -+ } else { -+ // Fill the unused array elements with nulls to release our references to the elements in it -+ for (int i = size; i < this.arr.length; i++) { -+ this.arr[i] = null; -+ } -+ } -+ -+ this.firstIndex = 0; -+ this.lastIndexExclusive = size; -+ -+ if (size == 0 || !this.isSorted) { -+ this.currentMaxSubTickOrder = Long.MIN_VALUE; -+ } else { -+ ScheduledTick tick = this.arr[size - 1]; -+ this.currentMaxSubTickOrder = tick == null ? Long.MIN_VALUE : tick.subTickOrder(); -+ } -+ } -+ -+ public void sort() { -+ if (this.isSorted) { -+ return; -+ } -+ this.removeNullsAndConsumed(); -+ Arrays.sort(this.arr, this.firstIndex, this.lastIndexExclusive, COMPARATOR); -+ this.isSorted = true; -+ this.unsortedPeekResult = null; -+ } -+ -+ public void removeNullsAndConsumed() { -+ int src = this.firstIndex; -+ int dst = 0; -+ while (src < this.lastIndexExclusive) { -+ ScheduledTick orderedTick = this.arr[src]; -+ if (orderedTick != null) { -+ this.arr[dst] = orderedTick; -+ dst++; -+ } -+ src++; -+ } -+ this.resize(dst); -+ } -+ -+ public ScheduledTick getTickAtIndex(int index) { -+ if (!this.isSorted) { -+ throw new IllegalStateException("Unexpected access on unsorted queue!"); -+ } -+ return this.arr[index]; -+ } -+ -+ public void setTickAtIndex(int index, ScheduledTick tick) { -+ if (!this.isSorted) { -+ throw new IllegalStateException("Unexpected access on unsorted queue!"); -+ } -+ this.arr[index] = tick; -+ } -+ -+ @SuppressWarnings("unchecked") -+ private static ScheduledTick[] copyArray(ScheduledTick[] src, int size) { -+ final ScheduledTick[] copy = new ScheduledTick[size]; -+ -+ if (size != 0) { -+ System.arraycopy(src, 0, copy, 0, Math.min(src.length, size)); -+ } -+ -+ return copy; -+ } -+ -+ @Override -+ public boolean isEmpty() { -+ return this.lastIndexExclusive <= this.firstIndex; -+ } -+} -diff --git a/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java b/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java -index 9f6c2e5b5d9e8d714a47c770e255d06c0ef7c190..826ced345c97bd2eb04749f42744a086fafc4ce8 100644 ---- a/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java -+++ b/src/main/java/net/minecraft/world/ticks/LevelChunkTicks.java -@@ -16,14 +16,37 @@ import javax.annotation.Nullable; - import net.minecraft.core.BlockPos; - import net.minecraft.nbt.ListTag; - import net.minecraft.world.level.ChunkPos; -+// Mirai start - lithium: world.tick_scheduler -+import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -+import it.unimi.dsi.fastutil.longs.Long2ReferenceAVLTreeMap; -+import it.unimi.dsi.fastutil.objects.ObjectIterator; -+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; -+import me.jellysquid.mods.lithium.common.world.scheduler.OrderedTickQueue; -+import net.minecraft.world.ticks.SavedTick; -+import net.minecraft.world.ticks.ScheduledTick; -+import net.minecraft.world.ticks.TickPriority; -+import java.util.Collection; -+// Mirai end - - public class LevelChunkTicks implements SerializableTickContainer, TickContainerAccess { -- private final Queue> tickQueue = new PriorityQueue<>(ScheduledTick.DRAIN_ORDER); -+ private Queue> tickQueue = new PriorityQueue<>(ScheduledTick.DRAIN_ORDER); // Mirai - remove final - @Nullable - private List> pendingTicks; -- private final Set> ticksPerPosition = new ObjectOpenCustomHashSet<>(ScheduledTick.UNIQUE_TICK_HASH); -+ private Set> ticksPerPosition = new ObjectOpenCustomHashSet<>(ScheduledTick.UNIQUE_TICK_HASH); // Mirai - remove final - @Nullable - private BiConsumer, ScheduledTick> onTickAdded; -+ // Mirai start - lithium: world.tick_scheduler -+ private static volatile Reference2IntOpenHashMap TYPE_2_INDEX; -+ -+ static { -+ TYPE_2_INDEX = new Reference2IntOpenHashMap<>(); -+ TYPE_2_INDEX.defaultReturnValue(-1); -+ } -+ -+ private final Long2ReferenceAVLTreeMap> tickQueuesByTimeAndPriority = new Long2ReferenceAVLTreeMap<>(); -+ private OrderedTickQueue nextTickQueue; -+ private final IntOpenHashSet allpendingTicks = new IntOpenHashSet(); -+ // Mirai end - - public LevelChunkTicks() { - } -@@ -35,34 +58,133 @@ public class LevelChunkTicks implements SerializableTickContainer, TickCon - this.ticksPerPosition.add(ScheduledTick.probe(savedTick.type(), savedTick.pos())); - } - -+ // Mirai start - lithium: world.tick_scheduler -+ //Remove replaced collections -+ if (this.pendingTicks != null) { -+ for (SavedTick orderedTick : this.pendingTicks) { -+ this.allpendingTicks.add(tickToInt(orderedTick.pos(), orderedTick.type())); -+ } -+ } -+ this.ticksPerPosition = null; -+ this.tickQueue = null; -+ // Mirai end -+ } -+ -+ // Mirai start - lithium: world.tick_scheduler -+ private static int tickToInt(BlockPos pos, Object type) { -+ //Y coordinate is 12 bits (BlockPos.toLong) -+ //X and Z coordinate is 4 bits each (This scheduler is for a single chunk) -+ //20 bits are in use for pos -+ //12 bits remaining for the type, so up to 4096 different tickable blocks/fluids (not block states) -> can upgrade to long if needed -+ int typeIndex = TYPE_2_INDEX.getInt(type); -+ if (typeIndex == -1) { -+ typeIndex = fixMissingType2Index(type); -+ } -+ -+ int ret = ((pos.getX() & 0xF) << 16) | ((pos.getY() & (0xfff)) << 4) | (pos.getZ() & 0xF); -+ ret |= typeIndex << 20; -+ return ret; - } - -+ //This method must be synchronized, otherwise type->int assignments can be overwritten and therefore change -+ //Uses clone and volatile store to ensure only fully initialized maps are used, all threads share the same mapping -+ private static synchronized int fixMissingType2Index(Object type) { -+ //check again, other thread might have replaced the collection -+ int typeIndex = TYPE_2_INDEX.getInt(type); -+ if (typeIndex == -1) { -+ Reference2IntOpenHashMap clonedType2Index = TYPE_2_INDEX.clone(); -+ clonedType2Index.put(type, typeIndex = clonedType2Index.size()); -+ TYPE_2_INDEX = clonedType2Index; -+ if (typeIndex >= 4096) { -+ throw new IllegalStateException("Lithium Tick Scheduler assumes at most 4096 different block types that receive scheduled pendingTicks exist! Open an issue on GitHub if you see this error!"); -+ } -+ } -+ return typeIndex; -+ } -+ // Mirai end -+ - public void setOnTickAdded(@Nullable BiConsumer, ScheduledTick> tickConsumer) { - this.onTickAdded = tickConsumer; - } - -+ // Mirai start - lithium: world.tick_scheduler -+ /** -+ * @author 2No2Name -+ * @reason use faster collections -+ */ - @Nullable - public ScheduledTick peek() { -- return this.tickQueue.peek(); -+ if (this.nextTickQueue == null) { -+ return null; -+ } -+ return this.nextTickQueue.peek(); - } - -+ /** -+ * @author 2No2Name -+ * @reason use faster collections -+ */ - @Nullable - public ScheduledTick poll() { -- ScheduledTick scheduledTick = this.tickQueue.poll(); -- if (scheduledTick != null) { -- this.ticksPerPosition.remove(scheduledTick); -+ ScheduledTick orderedTick = this.nextTickQueue.poll(); -+ if (orderedTick != null) { -+ if (this.nextTickQueue.isEmpty()) { -+ this.updateNextTickQueue(true); -+ } -+ this.allpendingTicks.remove(tickToInt(orderedTick.pos(), orderedTick.type())); -+ return orderedTick; - } -- -- return scheduledTick; -+ return null; - } - -+ /** -+ * @author 2No2Name -+ * @reason use faster collections -+ */ - @Override - public void schedule(ScheduledTick orderedTick) { -- if (this.ticksPerPosition.add(orderedTick)) { -- this.scheduleUnchecked(orderedTick); -+ int intTick = tickToInt(orderedTick.pos(), orderedTick.type()); -+ if (this.allpendingTicks.add(intTick)) { -+ this.queueTick(orderedTick); -+ } -+ } -+ -+ // Computes a timestamped key including the tick's priority -+ // Keys can be sorted in descending order to find what should be executed first -+ // 60 time bits, 4 priority bits -+ private static long getBucketKey(long time, TickPriority priority) { -+ //using priority.ordinal() as is not negative instead of priority.index -+ return (time << 4L) | (priority.ordinal() & 15); -+ } -+ -+ private void updateNextTickQueue(boolean elementRemoved) { -+ if (elementRemoved && this.nextTickQueue != null && this.nextTickQueue.isEmpty()) { -+ OrderedTickQueue removed = this.tickQueuesByTimeAndPriority.remove(this.tickQueuesByTimeAndPriority.firstLongKey()); -+ if (removed != this.nextTickQueue) { -+ throw new IllegalStateException("Next tick queue doesn't have the lowest key!"); -+ } -+ } -+ if (this.tickQueuesByTimeAndPriority.isEmpty()) { -+ this.nextTickQueue = null; -+ return; - } -+ long firstKey = this.tickQueuesByTimeAndPriority.firstLongKey(); -+ this.nextTickQueue = this.tickQueuesByTimeAndPriority.get(firstKey); -+ } -+ -+ private void queueTick(ScheduledTick orderedTick) { -+ OrderedTickQueue tickQueue = this.tickQueuesByTimeAndPriority.computeIfAbsent(getBucketKey(orderedTick.triggerTick(), orderedTick.priority()), key -> new OrderedTickQueue<>()); -+ if (tickQueue.isEmpty()) { -+ this.updateNextTickQueue(false); -+ } -+ tickQueue.offer(orderedTick); - -+ if (this.onTickAdded != null) { -+ //noinspection unchecked -+ this.onTickAdded.accept((LevelChunkTicks) (Object) this, orderedTick); -+ } - } -+ // Mirai end - - private void scheduleUnchecked(ScheduledTick orderedTick) { - this.tickQueue.add(orderedTick); -@@ -72,60 +194,93 @@ public class LevelChunkTicks implements SerializableTickContainer, TickCon - - } - -+ // Mirai start - lithium: world.tick_scheduler -+ /** -+ * @author 2No2Name -+ * @reason use faster collections -+ */ - @Override - public boolean hasScheduledTick(BlockPos pos, T type) { -- return this.ticksPerPosition.contains(ScheduledTick.probe(type, pos)); -+ return this.allpendingTicks.contains(tickToInt(pos, type)); - } - -+ /** -+ * @author 2No2Name -+ * @reason use faster collections -+ */ - public void removeIf(Predicate> predicate) { -- Iterator> iterator = this.tickQueue.iterator(); -- -- while(iterator.hasNext()) { -- ScheduledTick scheduledTick = iterator.next(); -- if (predicate.test(scheduledTick)) { -- iterator.remove(); -- this.ticksPerPosition.remove(scheduledTick); -+ for (ObjectIterator> tickQueueIterator = this.tickQueuesByTimeAndPriority.values().iterator(); tickQueueIterator.hasNext(); ) { -+ OrderedTickQueue nextTickQueue = tickQueueIterator.next(); -+ nextTickQueue.sort(); -+ boolean removed = false; -+ for (int i = 0; i < nextTickQueue.size(); i++) { -+ ScheduledTick nextTick = nextTickQueue.getTickAtIndex(i); -+ if (predicate.test(nextTick)) { -+ nextTickQueue.setTickAtIndex(i, null); -+ this.allpendingTicks.remove(tickToInt(nextTick.pos(), nextTick.type())); -+ removed = true; -+ } -+ } -+ if (removed) { -+ nextTickQueue.removeNullsAndConsumed(); -+ } -+ if (nextTickQueue.isEmpty()) { -+ tickQueueIterator.remove(); - } - } -- - } - -+ /** -+ * @author 2No2Name -+ * @reason use faster collections -+ */ - public Stream> getAll() { -- return this.tickQueue.stream(); -+ return this.tickQueuesByTimeAndPriority.values().stream().flatMap(Collection::stream); - } - -+ /** -+ * @author 2No2Name -+ * @reason not use unused field -+ */ - @Override - public int count() { -- return this.tickQueue.size() + (this.pendingTicks != null ? this.pendingTicks.size() : 0); -+ return this.allpendingTicks.size(); - } - -+ /** -+ * @author 2No2Name -+ * @reason not use unused field -+ */ - @Override - public ListTag save(long l, Function function) { -- ListTag listTag = new ListTag(); -+ ListTag nbtList = new ListTag(); - if (this.pendingTicks != null) { -- for(SavedTick savedTick : this.pendingTicks) { -- listTag.add(savedTick.save(function)); -+ for (SavedTick tick : this.pendingTicks) { -+ nbtList.add(tick.save(function)); - } - } -- -- for(ScheduledTick scheduledTick : this.tickQueue) { -- listTag.add(SavedTick.saveTick(scheduledTick, function, l)); -+ for (OrderedTickQueue nextTickQueue : this.tickQueuesByTimeAndPriority.values()) { -+ for (ScheduledTick orderedTick : nextTickQueue) { -+ nbtList.add(SavedTick.saveTick(orderedTick, function, l)); -+ } - } -- -- return listTag; -+ return nbtList; - } - -+ /** -+ * @author 2No2Name -+ * @reason use our datastructures -+ */ - public void unpack(long time) { - if (this.pendingTicks != null) { - int i = -this.pendingTicks.size(); -- -- for(SavedTick savedTick : this.pendingTicks) { -- this.scheduleUnchecked(savedTick.unpack(time, (long)(i++))); -+ for (SavedTick tick : this.pendingTicks) { -+ this.queueTick(tick.unpack(time, i++)); - } - } -- - this.pendingTicks = null; - } -+ // Mirai end - - public static LevelChunkTicks load(ListTag tickQueue, Function> nameToTypeFunction, ChunkPos pos) { - ImmutableList.Builder> builder = ImmutableList.builder(); diff --git a/patches/server/0094-Cache-block-break-animation-packet.patch b/patches/server/0091-Cache-block-break-animation-packet.patch similarity index 94% rename from patches/server/0094-Cache-block-break-animation-packet.patch rename to patches/server/0091-Cache-block-break-animation-packet.patch index fde499c..d647d51 100644 --- a/patches/server/0094-Cache-block-break-animation-packet.patch +++ b/patches/server/0091-Cache-block-break-animation-packet.patch @@ -7,7 +7,7 @@ Original license: GPLv3 Original project: https://github.com/Electroid/SportPaper diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 447fa39cf935072178503c3079c74ffe984d01c4..ef932eaedf1dbf4d2a90cab270516b71923d5678 100644 +index 789202faad1c9317984b14026bcd585bf7442b26..472d6a86b855cbf9cfab882e9c42b9e17943ddcc 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1540,6 +1540,7 @@ public class ServerLevel extends Level implements WorldGenLevel { diff --git a/patches/server/0095-Use-more-fastutil-data-structures.patch b/patches/server/0092-Use-more-fastutil-data-structures.patch similarity index 100% rename from patches/server/0095-Use-more-fastutil-data-structures.patch rename to patches/server/0092-Use-more-fastutil-data-structures.patch diff --git a/patches/server/0096-Optimize-Math.round-and-Math.hypot-functions.patch b/patches/server/0093-Optimize-Math.round-and-Math.hypot-functions.patch similarity index 99% rename from patches/server/0096-Optimize-Math.round-and-Math.hypot-functions.patch rename to patches/server/0093-Optimize-Math.round-and-Math.hypot-functions.patch index 5107382..beef2f7 100644 --- a/patches/server/0096-Optimize-Math.round-and-Math.hypot-functions.patch +++ b/patches/server/0093-Optimize-Math.round-and-Math.hypot-functions.patch @@ -164,10 +164,10 @@ index e3e80db89c18588322ffdaa0f9fd85e398cb1471..d947011b80ee14e7aaf74af3d9081fc7 throw ERROR_INVALID_TICK_COUNT.create(j); } else { diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 2a5bd17084238d8073d2f891f4c1af04d33fd09d..fe8b2de61fdce195210f270e33f508376b60f793 100644 +index 5e8a2cd78380727969c771eafa745550f3c5f237..7e9a837a39553c1c1aaf9c24c9db325392fa434e 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -2773,7 +2773,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop packet) { @@ -92,7 +92,7 @@ index 18c4f2eeb6bb427c1314608fc6a81e4642d92888..b029ae19db2bfde9b08950f41ba8a09e } diff --git a/src/main/java/wtf/etil/mirai/MiraiConfig.java b/src/main/java/wtf/etil/mirai/MiraiConfig.java -index f6f88a802c6f1892418fd6bcb8b4bc0b90fb6afb..13884ca2bd4e459498700e2fed1f0b4406538f53 100644 +index 38c01de9c2edd1b81802bdece037abb38aa3f746..3f879769032d8e01bfae51a604de2daf65e58014 100644 --- a/src/main/java/wtf/etil/mirai/MiraiConfig.java +++ b/src/main/java/wtf/etil/mirai/MiraiConfig.java @@ -244,4 +244,12 @@ public class MiraiConfig { diff --git a/patches/server/0102-PaperPR-Fix-exact-choice-recipe-book-clicks.patch b/patches/server/0099-PaperPR-Fix-exact-choice-recipe-book-clicks.patch similarity index 100% rename from patches/server/0102-PaperPR-Fix-exact-choice-recipe-book-clicks.patch rename to patches/server/0099-PaperPR-Fix-exact-choice-recipe-book-clicks.patch diff --git a/patches/server/0103-Fix-MC-238526.patch b/patches/server/0100-Fix-MC-238526.patch similarity index 100% rename from patches/server/0103-Fix-MC-238526.patch rename to patches/server/0100-Fix-MC-238526.patch diff --git a/patches/server/0104-Lobotomize-stuck-villagers.patch b/patches/server/0101-Lobotomize-stuck-villagers.patch similarity index 98% rename from patches/server/0104-Lobotomize-stuck-villagers.patch rename to patches/server/0101-Lobotomize-stuck-villagers.patch index ef58ed0..121fc7e 100644 --- a/patches/server/0104-Lobotomize-stuck-villagers.patch +++ b/patches/server/0101-Lobotomize-stuck-villagers.patch @@ -112,7 +112,7 @@ index f0b910df1ee471b4d72d97c6197ab14f2854976e..6ce32a52d621a0c2629568ea07e445f5 + // Purpur end } diff --git a/src/main/java/wtf/etil/mirai/MiraiConfig.java b/src/main/java/wtf/etil/mirai/MiraiConfig.java -index 13884ca2bd4e459498700e2fed1f0b4406538f53..b53da92ee9e96d76eada5ce7ed538378b88510c5 100644 +index 3f879769032d8e01bfae51a604de2daf65e58014..d45447551a6850e40ae37e9f88c9ba9aa1d3982e 100644 --- a/src/main/java/wtf/etil/mirai/MiraiConfig.java +++ b/src/main/java/wtf/etil/mirai/MiraiConfig.java @@ -252,4 +252,11 @@ public class MiraiConfig { diff --git a/patches/server/0105-Fix-a-bunch-of-vanilla-bugs.patch b/patches/server/0102-Fix-a-bunch-of-vanilla-bugs.patch similarity index 100% rename from patches/server/0105-Fix-a-bunch-of-vanilla-bugs.patch rename to patches/server/0102-Fix-a-bunch-of-vanilla-bugs.patch diff --git a/patches/server/0106-Fix-legacy-colors-in-console.patch b/patches/server/0103-Fix-legacy-colors-in-console.patch similarity index 100% rename from patches/server/0106-Fix-legacy-colors-in-console.patch rename to patches/server/0103-Fix-legacy-colors-in-console.patch diff --git a/patches/server/0107-PaperPR-Set-position-before-player-sending-on-dimens.patch b/patches/server/0104-PaperPR-Set-position-before-player-sending-on-dimens.patch similarity index 100% rename from patches/server/0107-PaperPR-Set-position-before-player-sending-on-dimens.patch rename to patches/server/0104-PaperPR-Set-position-before-player-sending-on-dimens.patch diff --git a/patches/server/0108-Set-BlockData-without-light-updates.patch b/patches/server/0105-Set-BlockData-without-light-updates.patch similarity index 100% rename from patches/server/0108-Set-BlockData-without-light-updates.patch rename to patches/server/0105-Set-BlockData-without-light-updates.patch diff --git a/patches/server/0109-Set-multiple-Team-settings-at-once.patch b/patches/server/0106-Set-multiple-Team-settings-at-once.patch similarity index 100% rename from patches/server/0109-Set-multiple-Team-settings-at-once.patch rename to patches/server/0106-Set-multiple-Team-settings-at-once.patch diff --git a/patches/server/0110-Smooth-Teleports.patch b/patches/server/0107-Smooth-Teleports.patch similarity index 100% rename from patches/server/0110-Smooth-Teleports.patch rename to patches/server/0107-Smooth-Teleports.patch diff --git a/patches/server/0111-Unfreeze-MappedRegistry.patch b/patches/server/0108-Unfreeze-MappedRegistry.patch similarity index 100% rename from patches/server/0111-Unfreeze-MappedRegistry.patch rename to patches/server/0108-Unfreeze-MappedRegistry.patch