diff --git a/patches/server/0004-Add-Linear-region-format.patch b/patches/server/0004-Add-Linear-region-format.patch index 4dce5d7..4c62c1f 100644 --- a/patches/server/0004-Add-Linear-region-format.patch +++ b/patches/server/0004-Add-Linear-region-format.patch @@ -587,10 +587,10 @@ index 25fe439c8d1e88a86e85ac9a4761425d98ee6c4f..c4d28d887b4cc71dc713b1e3f46bc80f regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound)); } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index cf8f93734121e5c1959959f0ba13ee4e6db31959..4c587f783f4c2207e4e1a1f4596c8f50e997d541 100644 +index 042ca6b3faae5249210567f2c26dff404974e1ff..7099a44a2322ab390c21e74668c8657dcc9e5e87 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -453,8 +453,8 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -426,8 +426,8 @@ public class ServerLevel extends Level implements WorldGenLevel { private static final class EntityRegionFileStorage extends net.minecraft.world.level.chunk.storage.RegionFileStorage { @@ -601,7 +601,7 @@ index cf8f93734121e5c1959959f0ba13ee4e6db31959..4c587f783f4c2207e4e1a1f4596c8f50 } protected void write(ChunkPos pos, net.minecraft.nbt.CompoundTag nbt) throws IOException { -@@ -693,7 +693,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -666,7 +666,7 @@ public class ServerLevel extends Level implements WorldGenLevel { // CraftBukkit end boolean flag2 = minecraftserver.forceSynchronousWrites(); DataFixer datafixer = minecraftserver.getFixerUpper(); diff --git a/patches/server/0012-Crash-on-broken-symlink.patch b/patches/server/0012-Crash-on-broken-symlink.patch index 301deb9..474f4d7 100644 --- a/patches/server/0012-Crash-on-broken-symlink.patch +++ b/patches/server/0012-Crash-on-broken-symlink.patch @@ -64,10 +64,10 @@ index c4d28d887b4cc71dc713b1e3f46bc80f4484a95d..f50507ab85282d261985ce9b186581f5 // Paper start this.dataRegionManager = new io.papermc.paper.chunk.SingleThreadChunkRegionManager(this.level, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new); diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 4c587f783f4c2207e4e1a1f4596c8f50e997d541..ad896c8a3060f5c8d85a8b5707317de646bf9cae 100644 +index 7099a44a2322ab390c21e74668c8657dcc9e5e87..475554797ffc279243ac0d88f1e619c3dd07bc4b 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -453,8 +453,8 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -426,8 +426,8 @@ public class ServerLevel extends Level implements WorldGenLevel { private static final class EntityRegionFileStorage extends net.minecraft.world.level.chunk.storage.RegionFileStorage { @@ -78,7 +78,7 @@ index 4c587f783f4c2207e4e1a1f4596c8f50e997d541..ad896c8a3060f5c8d85a8b5707317de6 } protected void write(ChunkPos pos, net.minecraft.nbt.CompoundTag nbt) throws IOException { -@@ -693,7 +693,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -666,7 +666,7 @@ public class ServerLevel extends Level implements WorldGenLevel { // CraftBukkit end boolean flag2 = minecraftserver.forceSynchronousWrites(); DataFixer datafixer = minecraftserver.getFixerUpper(); diff --git a/patches/server/0013-Toggle-void-trading.patch b/patches/server/0013-Toggle-void-trading.patch index 5574454..bce8b11 100644 --- a/patches/server/0013-Toggle-void-trading.patch +++ b/patches/server/0013-Toggle-void-trading.patch @@ -22,10 +22,10 @@ index f3f824d0ab1a2a72825c40b67192386479a0b34c..95ed6cb7b94797187d1011cab344e187 } } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index ad896c8a3060f5c8d85a8b5707317de646bf9cae..0df4672abb5e87587da8712b6febf6312e241cda 100644 +index 475554797ffc279243ac0d88f1e619c3dd07bc4b..475d0f3dd38e0407fa120d57e7d89216836538dd 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -2865,7 +2865,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2838,7 +2838,7 @@ public class ServerLevel extends Level implements WorldGenLevel { // Spigot Start if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message // Paper start diff --git a/patches/server/0015-Toggle-tick-level-when-empty.patch b/patches/server/0015-Toggle-tick-level-when-empty.patch index 3ebc727..0c1b8d2 100644 --- a/patches/server/0015-Toggle-tick-level-when-empty.patch +++ b/patches/server/0015-Toggle-tick-level-when-empty.patch @@ -22,10 +22,10 @@ index 6d7356cc07da58b1cef8d8963e790251d765de2c..601b9867d839f4928ba993ee8f00df9c public boolean fixVoidTrading = true; diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0df4672abb5e87587da8712b6febf6312e241cda..1818c5ae88c331fb900470436f72049165c9e9f4 100644 +index 475d0f3dd38e0407fa120d57e7d89216836538dd..245c3e63588379f51780963ba91bc6bf0a3feda6 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -825,7 +825,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -798,7 +798,7 @@ public class ServerLevel extends Level implements WorldGenLevel { timings.doSounds.stopTiming(); // Spigot regionizedWorldData.setHandlingTick(false); // Folia - regionised ticking gameprofilerfiller.pop(); diff --git a/patches/server/0022-Entity-ticking-throttling-removal-to-prevent-lag.patch b/patches/server/0022-Entity-ticking-throttling-removal-to-prevent-lag.patch index 83a8b2e..fa797ae 100644 --- a/patches/server/0022-Entity-ticking-throttling-removal-to-prevent-lag.patch +++ b/patches/server/0022-Entity-ticking-throttling-removal-to-prevent-lag.patch @@ -319,14 +319,10 @@ index 991e4c19763a34a6fead88363e007c2d11aad836..24a2d3f496727790f63cb66a2534d442 dev.kaiijumc.kaiiju.KaiijuConfig.registerCommands(); // Kaiiju end diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -<<<<<<< Updated upstream -index 1818c5ae88c331fb900470436f72049165c9e9f4..7938ce423422c1a2cb72a9b2e45c7bbb6f20ec91 100644 -======= index 245c3e63588379f51780963ba91bc6bf0a3feda6..6efc8b37d4ee929522f5646c972565b99aa45de3 100644 ->>>>>>> Stashed changes --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -849,6 +849,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -822,6 +822,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } // Folia end - region threading } @@ -334,7 +330,7 @@ index 245c3e63588379f51780963ba91bc6bf0a3feda6..6efc8b37d4ee929522f5646c972565b9 org.spigotmc.ActivationRange.activateEntities(this); // Spigot timings.entityTick.startTiming(); // Spigot regionizedWorldData.forEachTickingEntity((entity) -> { // Folia - regionised ticking -@@ -871,6 +872,13 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -844,6 +845,13 @@ public class ServerLevel extends Level implements WorldGenLevel { entity.stopRiding(); } @@ -348,7 +344,7 @@ index 245c3e63588379f51780963ba91bc6bf0a3feda6..6efc8b37d4ee929522f5646c972565b9 gameprofilerfiller.push("tick"); this.guardEntityTick(this::tickNonPassenger, entity); gameprofilerfiller.pop(); -@@ -878,6 +886,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -851,6 +859,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } } }); diff --git a/patches/server/0032-Option-to-disable-player-stats.patch b/patches/server/0032-Option-to-disable-player-stats.patch index c653250..110946d 100644 --- a/patches/server/0032-Option-to-disable-player-stats.patch +++ b/patches/server/0032-Option-to-disable-player-stats.patch @@ -21,10 +21,10 @@ index f49510c999ce5241f26dc9ba90a6148bf31467c7..b23f2df433d7ebc871f4009081c28ed9 public static String serverModName = "Kaiiju"; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index febd0ba72922462364eb65243640dcb693129e21..428da29b343eea9df25e5d719d5162faf0d9d7e5 100644 +index 817f79bfca1aec161cb4635b9c7a8e21b14db7eb..bba90683202b47284208416a37724e9d54266ffa 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2139,6 +2139,7 @@ public class ServerPlayer extends Player { +@@ -2081,6 +2081,7 @@ public class ServerPlayer extends Player { @Override public void awardStat(Stat stat, int amount) { diff --git a/patches/server/0033-Option-to-disable-achievements.patch b/patches/server/0033-Option-to-disable-achievements.patch index 48d09cb..dd3a88a 100644 --- a/patches/server/0033-Option-to-disable-achievements.patch +++ b/patches/server/0033-Option-to-disable-achievements.patch @@ -24,10 +24,10 @@ index 9f0095f2196133a8bcffd5306aa9ac0b99b2f8d7..31d66bb2fcf4bb7262df2d8006e307fe public boolean fixVoidTrading = true; diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b970de567aa 100644 +index bba90683202b47284208416a37724e9d54266ffa..6bbbd7d4a409140df65f52f36e413c67ebac5561 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -792,7 +792,7 @@ public class ServerPlayer extends Player { +@@ -734,7 +734,7 @@ public class ServerPlayer extends Player { @Override protected void onInsideBlock(BlockState state) { @@ -36,7 +36,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } @Override -@@ -839,9 +839,9 @@ public class ServerPlayer extends Player { +@@ -781,9 +781,9 @@ public class ServerPlayer extends Player { } } @@ -48,7 +48,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } this.trackStartFallingPosition(); -@@ -916,7 +916,7 @@ public class ServerPlayer extends Player { +@@ -858,7 +858,7 @@ public class ServerPlayer extends Player { } if (this.tickCount % 20 == 0) { @@ -57,7 +57,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } // CraftBukkit start - initialize oldLevel, fire PlayerLevelChangeEvent, and tick client-sided world border -@@ -945,7 +945,7 @@ public class ServerPlayer extends Player { +@@ -887,7 +887,7 @@ public class ServerPlayer extends Player { @Override public void resetFallDistance() { if (this.getHealth() > 0.0F && this.startingToFallPosition != null) { @@ -66,7 +66,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } this.startingToFallPosition = null; -@@ -964,7 +964,7 @@ public class ServerPlayer extends Player { +@@ -906,7 +906,7 @@ public class ServerPlayer extends Player { if (this.enteredLavaOnVehiclePosition == null) { this.enteredLavaOnVehiclePosition = this.position(); } else { @@ -75,7 +75,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } } -@@ -1168,7 +1168,7 @@ public class ServerPlayer extends Player { +@@ -1110,7 +1110,7 @@ public class ServerPlayer extends Player { this.handleTeamKill(s, s1, ObjectiveCriteria.TEAM_KILL); this.handleTeamKill(s1, s, ObjectiveCriteria.KILLED_BY_TEAM); @@ -84,7 +84,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } } -@@ -1286,7 +1286,7 @@ public class ServerPlayer extends Player { +@@ -1228,7 +1228,7 @@ public class ServerPlayer extends Player { this.wonGame = false; this.respawn((player) -> { @@ -93,7 +93,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 }, true); } -@@ -1788,14 +1788,14 @@ public class ServerPlayer extends Player { +@@ -1730,14 +1730,14 @@ public class ServerPlayer extends Player { maindimensionkey1 = resourcekey1; } // Paper end @@ -111,7 +111,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } if (maindimensionkey1 != Level.NETHER) { // CraftBukkit -@@ -1873,7 +1873,7 @@ public class ServerPlayer extends Player { +@@ -1815,7 +1815,7 @@ public class ServerPlayer extends Player { { Either either = super.startSleepInBed(blockposition, force).ifRight((unit) -> { this.awardStat(Stats.SLEEP_IN_BED); @@ -120,7 +120,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 }); if (!this.serverLevel().canSleepThroughNights()) { -@@ -2159,7 +2159,7 @@ public class ServerPlayer extends Player { +@@ -2101,7 +2101,7 @@ public class ServerPlayer extends Player { @Override public void triggerRecipeCrafted(Recipe recipe, List ingredients) { @@ -129,7 +129,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } @Override -@@ -2288,14 +2288,14 @@ public class ServerPlayer extends Player { +@@ -2230,14 +2230,14 @@ public class ServerPlayer extends Player { this.levitationStartPos = this.position(); } @@ -146,7 +146,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } @Override -@@ -2306,7 +2306,7 @@ public class ServerPlayer extends Player { +@@ -2248,7 +2248,7 @@ public class ServerPlayer extends Player { this.levitationStartPos = null; } @@ -155,7 +155,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 } @Override -@@ -2866,7 +2866,7 @@ public class ServerPlayer extends Player { +@@ -2808,7 +2808,7 @@ public class ServerPlayer extends Player { @Override protected void updateUsingItem(ItemStack stack) { @@ -164,7 +164,7 @@ index 428da29b343eea9df25e5d719d5162faf0d9d7e5..ad5830f419321e0f901d58a18bba7b97 super.updateUsingItem(stack); } -@@ -2895,7 +2895,7 @@ public class ServerPlayer extends Player { +@@ -2837,7 +2837,7 @@ public class ServerPlayer extends Player { Entity entity = item.getOwner(); if (entity != null) { diff --git a/patches/server/0044-Improve-container-checking-with-a-bitset.patch b/patches/server/0044-Improve-container-checking-with-a-bitset.patch new file mode 100644 index 0000000..f00ec28 --- /dev/null +++ b/patches/server/0044-Improve-container-checking-with-a-bitset.patch @@ -0,0 +1,457 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Paul Sauve +Date: Tue, 1 Aug 2023 03:38:09 +0200 +Subject: [PATCH] Improve container checking with a bitset + + +diff --git a/src/main/java/dev/kaiijumc/kaiiju/structs/ItemListWithBitset.java b/src/main/java/dev/kaiijumc/kaiiju/structs/ItemListWithBitset.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ee32b7c4a1ae1e23149694ecba5ab7bd347d6ca6 +--- /dev/null ++++ b/src/main/java/dev/kaiijumc/kaiiju/structs/ItemListWithBitset.java +@@ -0,0 +1,114 @@ ++package dev.kaiijumc.kaiiju.structs; ++ ++ ++import net.minecraft.core.NonNullList; ++import net.minecraft.world.item.ItemStack; ++import org.apache.commons.lang.Validate; ++import org.jetbrains.annotations.NotNull; ++ ++import java.util.AbstractList; ++import java.util.Arrays; ++import java.util.List; ++ ++public class ItemListWithBitset extends AbstractList { ++ public static ItemListWithBitset fromList(List list) { ++ if (list instanceof ItemListWithBitset ours) { ++ return ours; ++ } ++ return new ItemListWithBitset(list); ++ } ++ ++ private static ItemStack[] createArray(int size) { ++ ItemStack[] array = new ItemStack[size]; ++ Arrays.fill(array, ItemStack.EMPTY); ++ return array; ++ } ++ ++ private final ItemStack[] items; ++ ++ private long bitSet = 0; ++ private final long allBits; ++ ++ private static class OurNonNullList extends NonNullList { ++ protected OurNonNullList(List delegate) { ++ super(delegate, ItemStack.EMPTY); ++ } ++ } ++ ++ public final NonNullList nonNullList = new OurNonNullList(this); ++ ++ private ItemListWithBitset(List list) { ++ this(list.size()); ++ ++ for (int i = 0; i < list.size(); i++) { ++ this.set(i, list.get(i)); ++ } ++ } ++ ++ public ItemListWithBitset(int size) { ++ Validate.isTrue(size < Long.BYTES * 8, "size is too large"); ++ ++ this.items = createArray(size); ++ this.allBits = ((1L << size) - 1); ++ } ++ ++ public boolean isCompletelyEmpty() { ++ return this.bitSet == 0; ++ } ++ ++ public boolean hasFullStacks() { ++ return (this.bitSet & this.allBits) == allBits; ++ } ++ ++ @Override ++ public ItemStack set(int index, @NotNull ItemStack itemStack) { ++ ItemStack existing = this.items[index]; ++ ++ this.items[index] = itemStack; ++ ++ if (itemStack == ItemStack.EMPTY) { ++ this.bitSet &= ~(1L << index); ++ } else { ++ this.bitSet |= 1L << index; ++ } ++ ++ return existing; ++ } ++ ++ @NotNull ++ @Override ++ public ItemStack get(int var0) { ++ return this.items[var0]; ++ } ++ ++ @Override ++ public int size() { ++ return this.items.length; ++ } ++ ++ @Override ++ public void clear() { ++ Arrays.fill(this.items, ItemStack.EMPTY); ++ } ++ ++ // these are unsupported for block inventories which have a static size ++ @Override ++ public void add(int var0, ItemStack var1) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public ItemStack remove(int var0) { ++ throw new UnsupportedOperationException(); ++ } ++ ++ @Override ++ public String toString() { ++ return "ItemListWithBitset{" + ++ "items=" + Arrays.toString(items) + ++ ", bitSet=" + Long.toString(bitSet, 2) + ++ ", allBits=" + Long.toString(allBits, 2) + ++ ", size=" + this.items.length + ++ '}'; ++ } ++} +diff --git a/src/main/java/net/minecraft/world/CompoundContainer.java b/src/main/java/net/minecraft/world/CompoundContainer.java +index 241fec02e6869c638d3a160819b32173a081467b..62848ca68f532fa14241320df76d180c13072c34 100644 +--- a/src/main/java/net/minecraft/world/CompoundContainer.java ++++ b/src/main/java/net/minecraft/world/CompoundContainer.java +@@ -64,6 +64,23 @@ public class CompoundContainer implements Container { + this.container2 = second; + } + ++ // Kaiiju start - airplane - improve container checking with a bitset ++ @Override ++ public boolean hasEmptySlot(net.minecraft.core.Direction enumdirection) { ++ return this.container1.hasEmptySlot(null) || this.container2.hasEmptySlot(null); ++ } ++ ++ @Override ++ public boolean isCompletelyFull(net.minecraft.core.Direction enumdirection) { ++ return this.container1.isCompletelyFull(null) && this.container2.isCompletelyFull(null); ++ } ++ ++ @Override ++ public boolean isCompletelyEmpty(net.minecraft.core.Direction enumdirection) { ++ return this.container1.isCompletelyEmpty(null) && this.container2.isCompletelyEmpty(null); ++ } ++ // Kaiiju end ++ + @Override + public int getContainerSize() { + return this.container1.getContainerSize() + this.container2.getContainerSize(); +diff --git a/src/main/java/net/minecraft/world/Container.java b/src/main/java/net/minecraft/world/Container.java +index 04b1531572e8fff1e46fe1c94e7fc863841e0f66..ac1e21a4fc210424ea57c247d03914c54129de9c 100644 +--- a/src/main/java/net/minecraft/world/Container.java ++++ b/src/main/java/net/minecraft/world/Container.java +@@ -13,6 +13,63 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity; + // CraftBukkit end + + public interface Container extends Clearable { ++ // Kaiiju start - airplane - allow the inventory to override and optimize these frequent calls ++ default boolean hasEmptySlot(@org.jetbrains.annotations.Nullable net.minecraft.core.Direction enumdirection) { // there is a slot with 0 items in it ++ if (this instanceof WorldlyContainer worldlyContainer) { ++ for (int i : worldlyContainer.getSlotsForFace(enumdirection)) { ++ if (this.getItem(i).isEmpty()) { ++ return true; ++ } ++ } ++ } else { ++ int size = this.getContainerSize(); ++ for (int i = 0; i < size; i++) { ++ if (this.getItem(i).isEmpty()) { ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ ++ default boolean isCompletelyFull(@org.jetbrains.annotations.Nullable net.minecraft.core.Direction enumdirection) { // every stack is maxed ++ if (this instanceof WorldlyContainer worldlyContainer) { ++ for (int i : worldlyContainer.getSlotsForFace(enumdirection)) { ++ ItemStack itemStack = this.getItem(i); ++ if (itemStack.getCount() < itemStack.getMaxStackSize()) { ++ return false; ++ } ++ } ++ } else { ++ int size = this.getContainerSize(); ++ for (int i = 0; i < size; i++) { ++ ItemStack itemStack = this.getItem(i); ++ if (itemStack.getCount() < itemStack.getMaxStackSize()) { ++ return false; ++ } ++ } ++ } ++ return true; ++ } ++ ++ default boolean isCompletelyEmpty(@org.jetbrains.annotations.Nullable net.minecraft.core.Direction enumdirection) { ++ if (this instanceof WorldlyContainer worldlyContainer) { ++ for (int i : worldlyContainer.getSlotsForFace(enumdirection)) { ++ if (!this.getItem(i).isEmpty()) { ++ return false; ++ } ++ } ++ } else { ++ int size = this.getContainerSize(); ++ for (int i = 0; i < size; i++) { ++ if (!this.getItem(i).isEmpty()) { ++ return false; ++ } ++ } ++ } ++ return true; ++ } ++ // Kaiiju end + + int LARGE_MAX_STACK_SIZE = 64; + int DEFAULT_DISTANCE_LIMIT = 8; +diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +index 272095d7a09ab41227d741172735f66fd2798ce1..1f2e2d7726abd63bb46697697c91696387c819a2 100644 +--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java ++++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecartContainer.java +@@ -28,6 +28,7 @@ import org.bukkit.inventory.InventoryHolder; + public abstract class AbstractMinecartContainer extends AbstractMinecart implements ContainerEntity { + + private NonNullList itemStacks; ++ private dev.kaiijumc.kaiiju.structs.ItemListWithBitset itemStacksOptimized; // Kaiiju - airplane - implement ItemListWithBitset + @Nullable + public ResourceLocation lootTable; + public long lootTableSeed; +@@ -89,12 +90,18 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + + protected AbstractMinecartContainer(EntityType type, Level world) { + super(type, world); +- this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 ++ // Kaiiju start - airplane - use ItemListWithBitset ++ this.itemStacksOptimized = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize()); // CraftBukkit - SPIGOT-3513 ++ this.itemStacks = this.itemStacksOptimized.nonNullList; ++ // Kaiiju end + } + + protected AbstractMinecartContainer(EntityType type, double x, double y, double z, Level world) { + super(type, world, x, y, z); +- this.itemStacks = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); // CraftBukkit - SPIGOT-3513 ++ // Kaiiju start - airplane - use ItemListWithBitset ++ this.itemStacksOptimized = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize()); // CraftBukkit - SPIGOT-3513 ++ this.itemStacks = this.itemStacksOptimized.nonNullList; ++ // Kaiiju end + } + + @Override +@@ -156,6 +163,10 @@ public abstract class AbstractMinecartContainer extends AbstractMinecart impleme + protected void readAdditionalSaveData(CompoundTag nbt) { + super.readAdditionalSaveData(nbt); + this.lootableData.loadNbt(nbt); // Paper ++ // Kaiiju start - airplane - use ItemListWithBitset ++ this.itemStacksOptimized = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize()); // CraftBukkit - SPIGOT-3513 ++ this.itemStacks = this.itemStacksOptimized.nonNullList; ++ // Kaiiju end + this.readChestVehicleSaveData(nbt); + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +index a71414397bd45ee7bcacfeef0041d80dfa25f114..93db8c056f1ec0f998b480cfdea3666cbc54603c 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java +@@ -31,6 +31,7 @@ import org.bukkit.entity.HumanEntity; + public class ChestBlockEntity extends RandomizableContainerBlockEntity implements LidBlockEntity { + + private static final int EVENT_SET_OPEN_COUNT = 1; ++ private dev.kaiijumc.kaiiju.structs.ItemListWithBitset optimizedItems; // Kaiiju - airplane - implement ItemListWithBitset + private NonNullList items; + public final ContainerOpenersCounter openersCounter; + private final ChestLidController chestLidController; +@@ -65,9 +66,14 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + } + // CraftBukkit end + ++ private final boolean isNative = getClass().equals(ChestBlockEntity.class); // Kaiiju - airplane ++ + protected ChestBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); +- this.items = NonNullList.withSize(27, ItemStack.EMPTY); ++ // Kaiiju start - airplane - use ItemListWithBitset ++ this.optimizedItems = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(27); ++ this.items = this.optimizedItems.nonNullList; ++ // Kaiiju end + this.openersCounter = new ContainerOpenersCounter() { + @Override + protected void onOpen(Level world, BlockPos pos, BlockState state) { +@@ -98,6 +104,23 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + this.chestLidController = new ChestLidController(); + } + ++ // Kaiiju start - airplane - improve container checking with a bitset ++ @Override ++ public boolean hasEmptySlot(Direction enumdirection) { ++ return isNative ? !this.optimizedItems.hasFullStacks() : super.hasEmptySlot(enumdirection); ++ } ++ ++ @Override ++ public boolean isCompletelyFull(Direction enumdirection) { ++ return isNative ? this.optimizedItems.hasFullStacks() && super.isCompletelyFull(enumdirection) : super.isCompletelyFull(enumdirection); ++ } ++ ++ @Override ++ public boolean isCompletelyEmpty(Direction enumdirection) { ++ return isNative && this.optimizedItems.isCompletelyEmpty() || super.isCompletelyEmpty(enumdirection); ++ } ++ // Kaiiju end ++ + public ChestBlockEntity(BlockPos pos, BlockState state) { + this(BlockEntityType.CHEST, pos, state); + } +@@ -115,6 +138,10 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + @Override + public void load(CompoundTag nbt) { + super.load(nbt); ++ // Kaiiju start - airplane - use ItemListWithBitset ++ this.optimizedItems = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize()); ++ this.items = this.optimizedItems.nonNullList; ++ // Kaiiju end + this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); + if (!this.tryLoadLootTable(nbt)) { + ContainerHelper.loadAllItems(nbt, this.items); +@@ -187,7 +214,10 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement + + @Override + protected void setItems(NonNullList list) { +- this.items = list; ++ // Kaiiju start - airplane - use ItemListWithBitset ++ this.optimizedItems = dev.kaiijumc.kaiiju.structs.ItemListWithBitset.fromList(list); ++ this.items = this.optimizedItems.nonNullList; ++ // Kaiiju end + } + + @Override +diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +index 762b763f271c3208b4f8a7e346897207ec5beb6c..a212a62bc2b43b55e9040e2de8360d6e55a7dd86 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +@@ -48,6 +48,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + public static final int MOVE_ITEM_SPEED = 8; + public static final int HOPPER_CONTAINER_SIZE = 5; + private NonNullList items; ++ private dev.kaiijumc.kaiiju.structs.ItemListWithBitset optimizedItems; // Kaiiju - airplane - implement ItemListWithBitset + private int cooldownTime; + private long tickedGameTime; + +@@ -83,14 +84,37 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + + public HopperBlockEntity(BlockPos pos, BlockState state) { + super(BlockEntityType.HOPPER, pos, state); +- this.items = NonNullList.withSize(5, ItemStack.EMPTY); ++ // Kaiiju start - airplane - use ItemListWithBitset ++ this.optimizedItems = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(5); ++ this.items = this.optimizedItems.nonNullList; ++ // Kaiiju end + this.cooldownTime = -1; + } + ++ // Kaiiju start - airplane - improve container checking with a bitset ++ @Override ++ public boolean hasEmptySlot(Direction enumdirection) { ++ return !this.optimizedItems.hasFullStacks(); ++ } ++ ++ @Override ++ public boolean isCompletelyFull(Direction enumdirection) { ++ return this.optimizedItems.hasFullStacks() && super.isCompletelyFull(enumdirection); ++ } ++ ++ @Override ++ public boolean isCompletelyEmpty(Direction enumdirection) { ++ return this.optimizedItems.isCompletelyEmpty() || super.isCompletelyEmpty(enumdirection); ++ } ++ // Kaiiju end ++ + @Override + public void load(CompoundTag nbt) { + super.load(nbt); +- this.items = NonNullList.withSize(this.getContainerSize(), ItemStack.EMPTY); ++ // Kaiiju start - airplane - use ItemListWithBitset ++ this.optimizedItems = new dev.kaiijumc.kaiiju.structs.ItemListWithBitset(this.getContainerSize()); ++ this.items = this.optimizedItems.nonNullList; ++ // Kaiiju end + if (!this.tryLoadLootTable(nbt)) { + ContainerHelper.loadAllItems(nbt, this.items); + } +@@ -162,7 +186,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + flag = HopperBlockEntity.ejectItems(world, pos, state, (Container) blockEntity, blockEntity); // CraftBukkit + } + +- if (!blockEntity.inventoryFull()) { ++ if (!blockEntity.optimizedItems.hasFullStacks() || !blockEntity.inventoryFull()) { // Kaiiju - airplane + flag |= booleansupplier.getAsBoolean(); + } + +@@ -455,11 +479,11 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + } + + private static boolean isFullContainer(Container inventory, Direction direction) { +- return allMatch(inventory, direction, STACK_SIZE_TEST); // Paper - no streams ++ return inventory.isCompletelyFull(direction); // Kaiiju - airplane - use bitsets + } + + private static boolean isEmptyContainer(Container inv, Direction facing) { +- return allMatch(inv, facing, IS_EMPTY_TEST); ++ return inv.isCompletelyEmpty(facing); // Kaiiju - airplane - use bitsets + } + + public static boolean suckInItems(Level world, Hopper hopper) { +@@ -649,7 +673,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + + if (HopperBlockEntity.canPlaceItemInContainer(to, stack, slot, side)) { + boolean flag = false; +- boolean flag1 = to.isEmpty(); ++ boolean flag1 = to.isCompletelyEmpty(side); // Kaiiju - airplane - use bitsets + + if (itemstack1.isEmpty()) { + // Spigot start - SPIGOT-6693, InventorySubcontainer#setItem +@@ -844,7 +868,10 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen + + @Override + protected void setItems(NonNullList list) { +- this.items = list; ++ // Kaiiju start - airplane - use ItemListWithBitset ++ this.optimizedItems = dev.kaiijumc.kaiiju.structs.ItemListWithBitset.fromList(list); ++ this.items = this.optimizedItems.nonNullList; ++ // Kaiiju end + } + + public static void entityInside(Level world, BlockPos pos, BlockState state, Entity entity, HopperBlockEntity blockEntity) { +diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +index 081691f9710ff1115e4308f79ed49fbc38941193..648e28c5fba5c62e65f83fbb5ebc8836ffb166a9 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java +@@ -95,14 +95,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc + @Override + public boolean isEmpty() { + this.unpackLootTable((Player)null); +- // Paper start +- for (final ItemStack itemStack : this.getItems()) { +- if (!itemStack.isEmpty()) { +- return false; +- } +- } +- return true; +- // Paper end ++ return this.isCompletelyEmpty(null); // Kaiiju - airplane - use super + } + + @Override