From 397c6cce3ccc4d9afeb4ca0747df175de3bce0fd Mon Sep 17 00:00:00 2001 From: Etil <81570777+etil2jz@users.noreply.github.com> Date: Mon, 13 Dec 2021 17:39:44 +0100 Subject: [PATCH] more --- ...Optimize-inventory-API-item-handling.patch | 65 ++++++++ .../0068-lithium-ai.task.goat_jump.patch | 149 ----------------- ...-PaperPR-Fix-bees-aging-inside-hives.patch | 48 ++++++ ...0-Set-BlockData-without-light-update.patch | 151 ++++++++++++++++++ ...ment-updates-if-only-durability-chan.patch | 21 +++ 5 files changed, 285 insertions(+), 149 deletions(-) create mode 100644 patches/server/0068-Optimize-inventory-API-item-handling.patch delete mode 100644 patches/server/0068-lithium-ai.task.goat_jump.patch create mode 100644 patches/server/0069-PaperPR-Fix-bees-aging-inside-hives.patch create mode 100644 patches/server/0070-Set-BlockData-without-light-update.patch create mode 100644 patches/server/0071-Don-t-send-equipment-updates-if-only-durability-chan.patch diff --git a/patches/server/0068-Optimize-inventory-API-item-handling.patch b/patches/server/0068-Optimize-inventory-API-item-handling.patch new file mode 100644 index 0000000..4d9e892 --- /dev/null +++ b/patches/server/0068-Optimize-inventory-API-item-handling.patch @@ -0,0 +1,65 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Etil <81570777+etil2jz@users.noreply.github.com> +Date: Mon, 13 Dec 2021 16:59:28 +0100 +Subject: [PATCH] Optimize inventory API item handling + +Original code by Minebench, licensed under GNU General Public License v3.0 +You can find the original code on https://github.com/Minebench/Origami + +diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +index 396a4ae3d5a829eda78ef98561333aea300aa722..6c2f93fcca7c9cf694c873b2ef6024218f72f1a2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java ++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java +@@ -273,11 +273,13 @@ public class CraftInventory implements Inventory { + } + + private int firstPartial(ItemStack item) { +- ItemStack[] inventory = this.getStorageContents(); +- ItemStack filteredItem = CraftItemStack.asCraftCopy(item); + if (item == null) { + return -1; + } ++ // Origami start - Optimize inventory API (moved down from before null check) ++ ItemStack[] inventory = this.getStorageContents(); ++ ItemStack filteredItem = CraftItemStack.asCraftCopy(item); ++ // Origami end + for (int i = 0; i < inventory.length; i++) { + ItemStack cItem = inventory[i]; + if (cItem != null && cItem.getAmount() < cItem.getMaxStackSize() && cItem.isSimilar(filteredItem)) { +@@ -295,9 +297,10 @@ public class CraftInventory implements Inventory { + /* TODO: some optimization + * - Create a 'firstPartial' with a 'fromIndex' + * - Record the lastPartial per Material +- * - Cache firstEmpty result ++ * - Cache firstEmpty result // Implemented in Origami + */ + ++ int firstFree = -2; // Origami - Cache firstEmpty result + for (int i = 0; i < items.length; i++) { + ItemStack item = items[i]; + while (true) { +@@ -307,7 +310,11 @@ public class CraftInventory implements Inventory { + // Drat! no partial stack + if (firstPartial == -1) { + // Find a free spot! +- int firstFree = this.firstEmpty(); ++ // Origami start - Cache firstEmpty result ++ if (firstFree == -2) { ++ firstFree = this.firstEmpty(); ++ } ++ // Origami end + + if (firstFree == -1) { + // No space at all! +@@ -320,9 +327,11 @@ public class CraftInventory implements Inventory { + stack.setAmount(this.getMaxItemStack()); + this.setItem(firstFree, stack); + item.setAmount(item.getAmount() - this.getMaxItemStack()); ++ firstFree = -2; // Origami - Cache firstEmpty result + } else { + // Just store it + this.setItem(firstFree, item); ++ firstFree = -2; // Origami - Cache firstEmpty result + break; + } + } diff --git a/patches/server/0068-lithium-ai.task.goat_jump.patch b/patches/server/0068-lithium-ai.task.goat_jump.patch deleted file mode 100644 index 2e1d05e..0000000 --- a/patches/server/0068-lithium-ai.task.goat_jump.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Etil <81570777+etil2jz@users.noreply.github.com> -Date: Mon, 13 Dec 2021 14:43:37 +0100 -Subject: [PATCH] lithium: ai.task.goat_jump - -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/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java b/src/main/java/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java -index 76e4258b13482d081a0e7452d39edae00b348add..677861150a575dc7c85703e7b2aa4e9fa161904d 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java -+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/LongJumpToRandomPos.java -@@ -25,6 +25,9 @@ import net.minecraft.world.level.pathfinder.Path; - import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; - import net.minecraft.world.phys.AABB; - import net.minecraft.world.phys.Vec3; -+import it.unimi.dsi.fastutil.longs.LongArrayList; // Lithium -+import it.unimi.dsi.fastutil.shorts.ShortArrayList; // Lithium -+import net.minecraft.world.phys.Vec3; // Lithium - - public class LongJumpToRandomPos extends Behavior { - private static final int FIND_JUMP_TRIES = 20; -@@ -41,12 +44,26 @@ public class LongJumpToRandomPos extends Behavior { - private int findJumpTries; - private long prepareJumpStart; - private Function getJumpSound; -+ private int maxLongJumpHeight; -+ private int maxLongJumpWidth; -+ private final LongArrayList potentialTargets = new LongArrayList(); // Lithium -+ private final ShortArrayList potentialWeights = new ShortArrayList(); // Lithium -+ -+ // Lithium start -+ private static int findIndex(ShortArrayList weights, int weightedIndex) { -+ for (int i = 0; i < weights.size(); i++) { -+ weightedIndex -= weights.getShort(i); -+ if (weightedIndex < 0) { -+ return i; -+ } -+ } -+ return -1; -+ } -+ // Lithium end - - public LongJumpToRandomPos(UniformInt cooldownRange, int verticalRange, int horizontalRange, float maxRange, Function entityToSound) { - super(ImmutableMap.of(MemoryModuleType.LOOK_TARGET, MemoryStatus.REGISTERED, MemoryModuleType.LONG_JUMP_COOLDOWN_TICKS, MemoryStatus.VALUE_ABSENT, MemoryModuleType.LONG_JUMP_MID_JUMP, MemoryStatus.VALUE_ABSENT), 200); - this.timeBetweenLongJumps = cooldownRange; -- this.maxLongJumpHeight = verticalRange; -- this.maxLongJumpWidth = horizontalRange; -+ this.maxLongJumpHeight = maxLongJumpHeight; -+ this.maxLongJumpWidth = maxLongJumpWidth; - this.maxJumpVelocity = maxRange; - this.getJumpSound = entityToSound; - } -@@ -66,30 +83,63 @@ public class LongJumpToRandomPos extends Behavior { - return bl; - } - -+ // Lithium start -+ /** -+ * @author 2No2Name -+ * @reason only evaluate 20+ instead of ~100 possible jumps without affecting behavior -+ * [VanillaCopy] the whole method, commented changes -+ */ - @Override - protected void start(ServerLevel serverLevel, Mob mob, long l) { -+ this.potentialTargets.clear(); -+ this.potentialWeights.clear(); -+ int potentialTotalWeight = 0; - this.chosenJump = Optional.empty(); -- this.findJumpTries = 20; -+ this.findJumpTries = FIND_JUMP_TRIES; - this.jumpCandidates.clear(); - this.initialPosition = Optional.of(mob.position()); -- BlockPos blockPos = mob.blockPosition(); -- int i = blockPos.getX(); -- int j = blockPos.getY(); -- int k = blockPos.getZ(); -- Iterable iterable = BlockPos.betweenClosed(i - this.maxLongJumpWidth, j - this.maxLongJumpHeight, k - this.maxLongJumpWidth, i + this.maxLongJumpWidth, j + this.maxLongJumpHeight, k + this.maxLongJumpWidth); -- PathNavigation pathNavigation = mob.getNavigation(); -- -- for(BlockPos blockPos2 : iterable) { -- double d = blockPos2.distSqr(blockPos); -- if ((i != blockPos2.getX() || k != blockPos2.getZ()) && pathNavigation.isStableDestination(blockPos2) && mob.getPathfindingMalus(WalkNodeEvaluator.getBlockPathTypeStatic(mob.level, blockPos2.mutable())) == 0.0F) { -- Optional optional = this.calculateOptimalJumpVector(mob, Vec3.atCenterOf(blockPos2)); -- optional.ifPresent((vel) -> { -- this.jumpCandidates.add(new LongJumpToRandomPos.PossibleJump(new BlockPos(blockPos2), vel, Mth.ceil(d))); -- }); -+ BlockPos goatPos = mob.blockPosition(); -+ int goatX = goatPos.getX(); -+ int goatY = goatPos.getY(); -+ int goatZ = goatPos.getZ(); -+ Iterable iterable = BlockPos.betweenClosed(goatX - this.maxLongJumpWidth, goatY - this.maxLongJumpHeight, goatZ - this.maxLongJumpWidth, goatX + this.maxLongJumpWidth, goatY + this.maxLongJumpHeight, goatZ + this.maxLongJumpWidth); -+ PathNavigation entityNavigation = mob.getNavigation(); -+ -+ BlockPos.MutableBlockPos targetPosCopy = new BlockPos.MutableBlockPos(); -+ for (BlockPos targetPos : iterable) { -+ if (goatX == targetPos.getX() && goatZ == targetPos.getZ()) { -+ continue; - } -- } -+ double squaredDistance = targetPos.distSqr(goatPos); - -+ //Optimization: Evaluate the flight path check later (after random selection, but before world can be modified) -+ if (entityNavigation.isStableDestination(targetPos) && mob.getPathfindingMalus(WalkNodeEvaluator.getBlockPathTypeStatic(mob.level, targetPosCopy.set(targetPos))) == 0.0F) { -+ this.potentialTargets.add(targetPos.asLong()); -+ int weight = Mth.ceil(squaredDistance); -+ this.potentialWeights.add((short) weight); -+ potentialTotalWeight += weight; -+ } -+ } -+ // Optimization: Do the random picking of positions before doing the expensive the jump flight path validity check. -+ // up to FIND_JUMP_TRIES random jumpCandidates can be selected in keepRunning, so only this number of jumpCandidates needs to be generated -+ while (this.jumpCandidates.size() < FIND_JUMP_TRIES) { -+ // the number of random calls will be different from vanilla, but this is not reasonably detectable (not affecting world generation) -+ if (potentialTotalWeight == 0) { -+ return; // collection is empty/fully consumed, no more possible jumpCandidates available -+ } -+ int chosenIndex = findIndex(this.potentialWeights, serverLevel.random.nextInt(potentialTotalWeight)); -+ long chosenPos = this.potentialTargets.getLong(chosenIndex); -+ short chosenWeight = this.potentialWeights.set(chosenIndex, (short) 0); -+ potentialTotalWeight -= chosenWeight; -+ // Very expensive method call, it shifts bounding boxes around and checks for collisions with them -+ Optional optional = this.calculateOptimalJumpVector(mob, Vec3.atCenterOf(targetPosCopy.set(chosenPos))); -+ if (optional.isPresent()) { -+ //the weight in Target should be unused, as the random selection already took place -+ this.jumpCandidates.add(new LongJumpToRandomPos.PossibleJump(new BlockPos(targetPosCopy), optional.get(), chosenWeight)); -+ } -+ } - } -+ // Lithium end - - @Override - protected void tick(ServerLevel serverLevel, E mob, long l) { -@@ -106,7 +156,14 @@ public class LongJumpToRandomPos extends Behavior { - } - } else { - --this.findJumpTries; -- Optional optional = WeightedRandom.getRandomItem(serverLevel.random, this.jumpCandidates); -+ // Lithium start -+ Optional optional; -+ if (this.jumpCandidates.isEmpty()) { -+ optional = Optional.empty(); -+ } else { -+ optional = Optional.of(this.jumpCandidates.get(0)); -+ } -+ // Lithium end - if (optional.isPresent()) { - this.jumpCandidates.remove(optional.get()); - mob.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(optional.get().getJumpTarget())); diff --git a/patches/server/0069-PaperPR-Fix-bees-aging-inside-hives.patch b/patches/server/0069-PaperPR-Fix-bees-aging-inside-hives.patch new file mode 100644 index 0000000..f3efa6d --- /dev/null +++ b/patches/server/0069-PaperPR-Fix-bees-aging-inside-hives.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Etil <81570777+etil2jz@users.noreply.github.com> +Date: Mon, 13 Dec 2021 17:08:24 +0100 +Subject: [PATCH] PaperPR Fix bees aging inside hives + + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +index 8eabe7113822d35ff53390e981ea69ad5f07d67d..ff474c2245c608467c14eace5412b3a7507eafce 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java +@@ -322,7 +322,7 @@ public class BeehiveBlockEntity extends BlockEntity { + + for (Iterator iterator = bees.iterator(); iterator.hasNext(); ++tileentitybeehive_hivebee.ticksInHive) { + tileentitybeehive_hivebee = (BeehiveBlockEntity.BeeData) iterator.next(); +- if (tileentitybeehive_hivebee.ticksInHive > tileentitybeehive_hivebee.minOccupationTicks) { ++ if (tileentitybeehive_hivebee.exitTickCounter > tileentitybeehive_hivebee.minOccupationTicks) { // Paper - use exitTickCounter + BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus = tileentitybeehive_hivebee.entityData.getBoolean("HasNectar") ? BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED : BeehiveBlockEntity.BeeReleaseStatus.BEE_RELEASED; + + if (BeehiveBlockEntity.releaseOccupant(world, pos, state, tileentitybeehive_hivebee, (List) null, tileentitybeehive_releasestatus, flowerPos)) { +@@ -330,10 +330,11 @@ public class BeehiveBlockEntity extends BlockEntity { + iterator.remove(); + // CraftBukkit start + } else { +- tileentitybeehive_hivebee.ticksInHive = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable ++ tileentitybeehive_hivebee.exitTickCounter = tileentitybeehive_hivebee.minOccupationTicks / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable // Paper - use exitTickCounter to keep actual bee life + // CraftBukkit end + } + } ++ tileentitybeehive_hivebee.exitTickCounter++; // Paper + } + + if (flag) { +@@ -422,6 +423,7 @@ public class BeehiveBlockEntity extends BlockEntity { + + final CompoundTag entityData; + int ticksInHive; ++ int exitTickCounter; // Paper - separate counter for checking if bee should exit to reduce exit attempts + final int minOccupationTicks; + + BeeData(CompoundTag entityData, int ticksInHive, int minOccupationTicks) { +@@ -429,6 +431,7 @@ public class BeehiveBlockEntity extends BlockEntity { + this.entityData = entityData; + this.ticksInHive = ticksInHive; + this.minOccupationTicks = minOccupationTicks; ++ this.exitTickCounter = this.ticksInHive; // Paper + } + } + } diff --git a/patches/server/0070-Set-BlockData-without-light-update.patch b/patches/server/0070-Set-BlockData-without-light-update.patch new file mode 100644 index 0000000..ec7c548 --- /dev/null +++ b/patches/server/0070-Set-BlockData-without-light-update.patch @@ -0,0 +1,151 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Etil <81570777+etil2jz@users.noreply.github.com> +Date: Mon, 13 Dec 2021 17:33:29 +0100 +Subject: [PATCH] Set BlockData without light update + +Original code by Cryptite, licensed under MIT +You can find the original code on https://github.com/Cryptite/Slice + +diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +index 9b25d36fe5230e287d81b99be31b9eddd8e76002..2477b1edc73f295414dd67acfd16e17c100e4260 100644 +--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java ++++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java +@@ -226,7 +226,7 @@ public class WorldGenRegion implements WorldGenLevel { + Block.dropResources(iblockdata, this.level, pos, tileentity, breakingEntity, ItemStack.EMPTY); + } + +- return this.setBlock(pos, Blocks.AIR.defaultBlockState(), 3, maxUpdateDepth); ++ return this.setBlock(pos, Blocks.AIR.defaultBlockState(), 3, maxUpdateDepth, true); + } + } + +@@ -292,7 +292,7 @@ public class WorldGenRegion implements WorldGenLevel { + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { ++ public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, boolean checkLight) { + if (!this.ensureCanWrite(pos)) { + return false; + } else { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 2eb8ce55cdca9bcc2e9178c498c750dca9e9939b..e5f1520d07a9056d8bc38e44719e8e824041e5b5 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -643,12 +643,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + + @Override +- public final boolean setBlock(BlockPos pos, BlockState state, int flags) { // Paper - final for inline +- return this.setBlock(pos, state, flags, 512); ++ public final boolean setBlock(BlockPos pos, BlockState state, int flags, boolean checkLight) { // Paper - final for inline ++ return this.setBlock(pos, state, flags, 512, checkLight); + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { ++ public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, boolean checkLight) { + // CraftBukkit start - tree generation + if (this.captureTreeGeneration) { + // Paper start +@@ -695,7 +695,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } else { + BlockState iblockdata2 = this.getBlockState(pos); + +- if ((flags & 128) == 0 && iblockdata2 != iblockdata1 && (iblockdata2.getLightBlock(this, pos) != iblockdata1.getLightBlock(this, pos) || iblockdata2.getLightEmission() != iblockdata1.getLightEmission() || iblockdata2.useShapeForLightOcclusion() || iblockdata1.useShapeForLightOcclusion())) { ++ if (checkLight && (flags & 128) == 0 && iblockdata2 != iblockdata1 && (iblockdata2.getLightBlock(this, pos) != iblockdata1.getLightBlock(this, pos) || iblockdata2.getLightEmission() != iblockdata1.getLightEmission() || iblockdata2.useShapeForLightOcclusion() || iblockdata1.useShapeForLightOcclusion())) { + this.getProfiler().push("queueCheckLight"); + this.getChunkSource().getLightEngine().checkBlock(pos); + this.getProfiler().pop(); +@@ -837,7 +837,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY); + } + +- boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, maxUpdateDepth); ++ boolean flag1 = this.setBlock(pos, fluid.createLegacyBlock(), 3, maxUpdateDepth, true); + + if (flag1) { + this.gameEvent(breakingEntity, GameEvent.BLOCK_DESTROY, pos); +diff --git a/src/main/java/net/minecraft/world/level/LevelWriter.java b/src/main/java/net/minecraft/world/level/LevelWriter.java +index 134e5ec79bf2dddd4e31930f8a7cb2c02fa29518..fd72d278a2719911a46b6bc9e7da2dc24bbe681e 100644 +--- a/src/main/java/net/minecraft/world/level/LevelWriter.java ++++ b/src/main/java/net/minecraft/world/level/LevelWriter.java +@@ -7,10 +7,14 @@ import net.minecraft.world.level.block.state.BlockState; + + public interface LevelWriter { + +- boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth); ++ boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, boolean checkLight); + + default boolean setBlock(BlockPos pos, BlockState state, int flags) { +- return this.setBlock(pos, state, flags, 512); ++ return this.setBlock(pos, state, flags, 512, true); ++ } ++ ++ default boolean setBlock(BlockPos pos, BlockState state, int flags, boolean checkLight) { ++ return this.setBlock(pos, state, flags, 512, checkLight); + } + + boolean removeBlock(BlockPos pos, boolean move); +diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java +index ab5b9f00123e2ede2931ffc520684e482aac49b4..e88e46aac3fa07a330c9f686f563c6d5fbfa3d70 100644 +--- a/src/main/java/net/minecraft/world/level/block/Block.java ++++ b/src/main/java/net/minecraft/world/level/block/Block.java +@@ -195,7 +195,7 @@ public class Block extends BlockBehaviour implements ItemLike { + world.destroyBlock(pos, (flags & 32) == 0, (Entity) null, maxUpdateDepth); + } + } else { +- world.setBlock(pos, newState, flags & -33, maxUpdateDepth); ++ world.setBlock(pos, newState, flags & -33, maxUpdateDepth, true); + } + } + +diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +index ca320ef8a28fe15b32197669419981c4c2fcafd9..056562c7d86528e34a47974c1b870c385a30c0b9 100644 +--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java ++++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +@@ -178,15 +178,20 @@ public class CraftBlock implements Block { + + @Override + public void setBlockData(BlockData data, boolean applyPhysics) { ++ setBlockData(data, applyPhysics, true); ++ } ++ ++ @Override ++ public void setBlockData(BlockData data, boolean applyPhysics, boolean checkLight) { + Preconditions.checkArgument(data != null, "BlockData cannot be null"); +- this.setTypeAndData(((CraftBlockData) data).getState(), applyPhysics); ++ this.setTypeAndData(((CraftBlockData) data).getState(), applyPhysics, checkLight); + } + + boolean setTypeAndData(final net.minecraft.world.level.block.state.BlockState blockData, final boolean applyPhysics) { + return CraftBlock.setTypeAndData(this.world, this.position, this.getNMS(), blockData, applyPhysics); + } + +- public static boolean setTypeAndData(LevelAccessor world, BlockPos position, net.minecraft.world.level.block.state.BlockState old, net.minecraft.world.level.block.state.BlockState blockData, boolean applyPhysics) { ++ public static boolean setTypeAndData(LevelAccessor world, BlockPos position, net.minecraft.world.level.block.state.BlockState old, net.minecraft.world.level.block.state.BlockState blockData, boolean applyPhysics, boolean checkLight) { + // SPIGOT-611: need to do this to prevent glitchiness. Easier to handle this here (like /setblock) than to fix weirdness in tile entity cleanup + if (old.hasBlockEntity() && blockData.getBlock() != old.getBlock()) { // SPIGOT-3725 remove old tile entity if block changes + // SPIGOT-4612: faster - just clear tile +@@ -200,7 +205,7 @@ public class CraftBlock implements Block { + if (applyPhysics) { + return world.setBlock(position, blockData, 3); + } else { +- boolean success = world.setBlock(position, blockData, 2 | 16 | 1024); // NOTIFY | NO_OBSERVER | NO_PLACE (custom) ++ boolean success = world.setBlock(position, blockData, 2 | 16 | 1024, checkLight); // NOTIFY | NO_OBSERVER | NO_PLACE (custom) + if (success && world instanceof net.minecraft.world.level.Level) { + world.getMinecraftWorld().sendBlockUpdated( + position, +diff --git a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +index 4c6cbfbcb5a7876e6b556b59c54e9a4cedf7843e..0cec147b0c291ab92b1fc93df40bf39c473d862a 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/DummyGeneratorAccess.java +@@ -245,7 +245,7 @@ public class DummyGeneratorAccess implements WorldGenLevel { + } + + @Override +- public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { ++ public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth, boolean checkLight) { + return false; + } + diff --git a/patches/server/0071-Don-t-send-equipment-updates-if-only-durability-chan.patch b/patches/server/0071-Don-t-send-equipment-updates-if-only-durability-chan.patch new file mode 100644 index 0000000..11597a7 --- /dev/null +++ b/patches/server/0071-Don-t-send-equipment-updates-if-only-durability-chan.patch @@ -0,0 +1,21 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Etil <81570777+etil2jz@users.noreply.github.com> +Date: Mon, 13 Dec 2021 17:35:59 +0100 +Subject: [PATCH] Don't send equipment updates if only durability changed + +Original code by Cryptite, licensed under MIT +You can find the original code on https://github.com/Cryptite/Slice + +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 2af803f061217649f10d778d376cd91de4417e66..964cf2583b646c54724f02907c5501ddd6b243ad 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -3044,7 +3044,7 @@ public abstract class LivingEntity extends Entity { + + ItemStack itemstack1 = this.getItemBySlot(enumitemslot); + +- if (!ItemStack.matches(itemstack1, itemstack)) { ++ if (!ItemStack.isSameIgnoreDurability(itemstack1, itemstack)) { + // Paper start - PlayerArmorChangeEvent + if (this instanceof ServerPlayer && enumitemslot.getType() == EquipmentSlot.Type.ARMOR) { + final org.bukkit.inventory.ItemStack oldItem = CraftItemStack.asBukkitCopy(itemstack);