From 64b98ef1101a6d013b0199b3a356b4e21b20cd90 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Mon, 15 Jan 2024 12:38:39 +0100 Subject: [PATCH] [ci skip] Add more patch identifying comments, merge related patches --- ...ItemEvent-and-EntityCompostItemEvent.patch | 8 +- .../Add-Sign-getInteractableSideFor.patch | 8 +- .../Add-event-for-player-editing-sign.patch | 20 ++--- ...setting-for-proxy-online-mode-status.patch | 2 +- .../Array-backed-synched-entity-data.patch | 6 +- ...-Lazy-Initialization-for-Enum-Fields.patch | 8 +- .../Call-missing-BlockDispenseEvent.patch | 16 ++-- ...anhasbukkit-default-if-alias-block-e.patch | 2 +- ...e-profiles-that-have-no-UUID-and-no-.patch | 2 +- .../server/Expand-PlayerItemMendEvent.patch | 16 ++-- .../Fix-DamageCause-for-Falling-Blocks.patch | 4 +- ...ity-drop-not-updating-the-client-inv.patch | 4 +- ...hives-generating-from-using-bonemeal.patch | 8 +- patches/server/Fix-block-place-logic.patch | 12 +-- ...permission-levels-for-command-blocks.patch | 10 +-- ...nventories-returning-null-Locations.patch} | 12 +-- ...und-playing-for-BlockItem-ItemStacks.patch | 4 +- .../Fix-text-display-error-on-spawn.patch | 2 +- patches/server/Lag-compensation-ticks.patch | 4 +- .../Only-capture-actual-tree-growth.patch | 2 +- ...ck-item-frames-if-players-can-see-it.patch | 2 +- patches/server/Optimize-Hoppers.patch | 76 +++++++++---------- ...nts-being-fired-from-unloaded-chunks.patch | 4 +- ...expired-keys-from-impacting-new-join.patch | 12 +-- ...tch => Properly-cancel-usable-items.patch} | 14 ++-- ...esh-ProjectileSource-for-projectiles.patch | 16 ++-- ...ayerChunkLoaderData-in-order-to-prep.patch | 2 +- ...uence-violations-like-they-should-be.patch | 2 +- .../Use-array-for-gamerule-storage.patch | 16 ++-- 29 files changed, 147 insertions(+), 147 deletions(-) rename patches/server/{Fix-certain-inventories-returning-null-Locations.patch => Fix-inventories-returning-null-Locations.patch} (88%) rename patches/server/{Properly-Cancel-Usable-Items.patch => Properly-cancel-usable-items.patch} (89%) diff --git a/patches/server/Add-CompostItemEvent-and-EntityCompostItemEvent.patch b/patches/server/Add-CompostItemEvent-and-EntityCompostItemEvent.patch index e3e57658f2..c809ab5204 100644 --- a/patches/server/Add-CompostItemEvent-and-EntityCompostItemEvent.patch +++ b/patches/server/Add-CompostItemEvent-and-EntityCompostItemEvent.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 float f = ComposterBlock.COMPOSTABLES.getFloat(itemstack.getItem()); - if ((i != 0 || f <= 0.0F) && rand >= (double) f) { -+ // Paper start ++ // Paper start - Add CompostItemEvent and EntityCompostItemEvent + boolean willRaiseLevel = !((i != 0 || f <= 0.0F) && rand >= (double) f); + final io.papermc.paper.event.block.CompostItemEvent event; + if (entity == null) { @@ -27,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + willRaiseLevel = event.willRaiseLevel(); + + if (!willRaiseLevel) { -+ // Paper end ++ // Paper end - Add CompostItemEvent and EntityCompostItemEvent return iblockdata; } else { int j = i + 1; @@ -35,11 +35,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.changed = true; BlockState iblockdata = ComposterBlock.addItem((Entity) null, this.state, this.level, this.pos, itemstack); -+ // Paper start ++ // Paper start - Add CompostItemEvent and EntityCompostItemEvent + if (iblockdata == null) { + return; + } -+ // Paper end ++ // Paper end - Add CompostItemEvent and EntityCompostItemEvent this.level.levelEvent(1500, this.pos, iblockdata != this.state ? 1 : 0); this.removeItemNoUpdate(0); } diff --git a/patches/server/Add-Sign-getInteractableSideFor.patch b/patches/server/Add-Sign-getInteractableSideFor.patch index 12a693db02..03903e0992 100644 --- a/patches/server/Add-Sign-getInteractableSideFor.patch +++ b/patches/server/Add-Sign-getInteractableSideFor.patch @@ -12,11 +12,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public boolean isFacingFrontText(net.minecraft.world.entity.player.Player player) { -+ // Paper start ++ // Paper start - Add Sign#getInteractableSideFor + return this.isFacingFrontText(player.getX(), player.getZ()); + } + public boolean isFacingFrontText(double x, double z) { -+ // Paper end ++ // Paper end - Add Sign#getInteractableSideFor Block block = this.getBlockState().getBlock(); if (block instanceof SignBlock) { @@ -24,8 +24,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Vec3 vec3d = blocksign.getSignHitboxCenterPosition(this.getBlockState()); - double d0 = player.getX() - ((double) this.getBlockPos().getX() + vec3d.x); - double d1 = player.getZ() - ((double) this.getBlockPos().getZ() + vec3d.z); -+ double d0 = x - ((double) this.getBlockPos().getX() + vec3d.x); // Paper -+ double d1 = z - ((double) this.getBlockPos().getZ() + vec3d.z); // Paper ++ double d0 = x - ((double) this.getBlockPos().getX() + vec3d.x); // Paper - Add Sign#getInteractableSideFor ++ double d1 = z - ((double) this.getBlockPos().getZ() + vec3d.z); // Paper - Add Sign#getInteractableSideFor float f = blocksign.getYRotationDegrees(this.getBlockState()); float f1 = (float) (Mth.atan2(d1, d0) * 57.2957763671875D) - 90.0F; diff --git a/patches/server/Add-event-for-player-editing-sign.patch b/patches/server/Add-event-for-player-editing-sign.patch index 5c2fe297f4..0183110dce 100644 --- a/patches/server/Add-event-for-player-editing-sign.patch +++ b/patches/server/Add-event-for-player-editing-sign.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (world.getBlockEntity(SignItem.openSign) instanceof SignBlockEntity tileentitysign) { if (world.getBlockState(SignItem.openSign).getBlock() instanceof SignBlock blocksign) { - blocksign.openTextEdit(entityhuman, tileentitysign, true, org.bukkit.event.player.PlayerSignOpenEvent.Cause.PLACE); // Craftbukkit -+ blocksign.openTextEdit(entityhuman, tileentitysign, true, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLACE); // Paper ++ blocksign.openTextEdit(entityhuman, tileentitysign, true, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLACE); // Paper - Add PlayerOpenSignEvent } } } finally { @@ -26,7 +26,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return InteractionResult.SUCCESS; } else if (!this.otherPlayerIsEditingSign(player, tileentitysign) && player.mayBuild() && this.hasEditableText(player, tileentitysign, flag1)) { - this.openTextEdit(player, tileentitysign, flag1, org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT); // CraftBukkit -+ this.openTextEdit(player, tileentitysign, flag1, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.INTERACT); // Paper ++ this.openTextEdit(player, tileentitysign, flag1, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.INTERACT); // Paper - Add PlayerOpenSignEvent return this.getInteractionResult(flag); } else { return InteractionResult.PASS; @@ -34,7 +34,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return blockpropertywood; } -+ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper ++ @io.papermc.paper.annotation.DoNotUse @Deprecated // Paper - Add PlayerOpenSignEvent public void openTextEdit(Player player, SignBlockEntity blockEntity, boolean front) { - // Craftbukkit start - this.openTextEdit(player, blockEntity, front, org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN); @@ -42,7 +42,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - - public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, org.bukkit.event.player.PlayerSignOpenEvent.Cause cause) { - if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, cause)) { -+ // Paper start - PlayerOpenSignEvent ++ // Paper start - Add PlayerOpenSignEvent + this.openTextEdit(player, blockEntity, front, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.UNKNOWN); + } + public void openTextEdit(Player entityhuman, SignBlockEntity tileentitysign, boolean flag, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause cause) { @@ -62,12 +62,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + case INTERACT -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.INTERACT; + case UNKNOWN -> org.bukkit.event.player.PlayerSignOpenEvent.Cause.UNKNOWN; + }; -+ // Paper end - PlayerOpenSignEvent -+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, legacyCause)) { // Paper ++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerSignOpenEvent(entityhuman, tileentitysign, flag, legacyCause)) { ++ // Paper end - Add PlayerOpenSignEvent return; } - // Craftbukkit end -+ } // Paper ++ } // Paper - Add PlayerOpenSignEvent tileentitysign.setAllowedPlayerEditor(entityhuman.getUUID()); entityhuman.openTextEdit(tileentitysign, flag); } @@ -79,15 +79,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Preconditions.checkArgument(sign.isPlaced(), "Sign must be placed"); Preconditions.checkArgument(sign.getWorld() == player.getWorld(), "Sign must be in same world as Player"); -+ // Paper start ++ // Paper start - Add PlayerOpenSignEvent + io.papermc.paper.event.player.PlayerOpenSignEvent event = new io.papermc.paper.event.player.PlayerOpenSignEvent((Player) player, sign, side, io.papermc.paper.event.player.PlayerOpenSignEvent.Cause.PLUGIN); + if (!event.callEvent()) return; + if (PlayerSignOpenEvent.getHandlerList().getRegisteredListeners().length > 0) { -+ // Paper end ++ // Paper end - Add PlayerOpenSignEvent if (!CraftEventFactory.callPlayerSignOpenEvent(player, sign, side, PlayerSignOpenEvent.Cause.PLUGIN)) { return; } -+ } // Paper ++ } // Paper - Add PlayerOpenSignEvent SignBlockEntity handle = ((CraftSign) sign).getTileEntity(); handle.setAllowedPlayerEditor(player.getUniqueId()); diff --git a/patches/server/Add-setting-for-proxy-online-mode-status.patch b/patches/server/Add-setting-for-proxy-online-mode-status.patch index 09adab8b69..c077e6afdd 100644 --- a/patches/server/Add-setting-for-proxy-online-mode-status.patch +++ b/patches/server/Add-setting-for-proxy-online-mode-status.patch @@ -30,7 +30,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } }; -- if (!org.apache.commons.lang3.StringUtils.isBlank(name)) // Paper - Don't lookup a profile with a blank name) +- if (!org.apache.commons.lang3.StringUtils.isBlank(name)) // Paper - Don't lookup a profile with a blank name + if (!org.apache.commons.lang3.StringUtils.isBlank(name) // Paper - Don't lookup a profile with a blank name + && io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode()) // Paper - Add setting for proxy online mode status repository.findProfilesByNames(new String[]{name}, profilelookupcallback); diff --git a/patches/server/Array-backed-synched-entity-data.patch b/patches/server/Array-backed-synched-entity-data.patch index 0327cc6180..b2dfe6d721 100644 --- a/patches/server/Array-backed-synched-entity-data.patch +++ b/patches/server/Array-backed-synched-entity-data.patch @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private static final int DEFAULT_ENTRY_COUNT = 10; + private static final int GROW_FACTOR = 8; + private SynchedEntityData.DataItem[] itemsArray = new SynchedEntityData.DataItem[DEFAULT_ENTRY_COUNT]; -+ // Paper end ++ // Paper end - array backed synched entity data public SynchedEntityData(Entity trackedEntity) { this.entity = trackedEntity; @@ -33,7 +33,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + this.itemsArray[key.getId()] = datawatcher_item; -+ // Paper end ++ // Paper end - array backed synched entity data } public boolean hasItem(EntityDataAccessor key) { @@ -50,7 +50,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + return (DataItem) this.itemsArray[id]; -+ // Paper end ++ // Paper end - array backed synched entity data // Spigot end } diff --git a/patches/server/Avoid-Lazy-Initialization-for-Enum-Fields.patch b/patches/server/Avoid-Lazy-Initialization-for-Enum-Fields.patch index ee257d97ff..63393b27b3 100644 --- a/patches/server/Avoid-Lazy-Initialization-for-Enum-Fields.patch +++ b/patches/server/Avoid-Lazy-Initialization-for-Enum-Fields.patch @@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.permutation = axisTransformation; this.transformation = (new Matrix3f()).scaling(flipX ? -1.0F : 1.0F, flipY ? -1.0F : 1.0F, flipZ ? -1.0F : 1.0F); this.transformation.mul(axisTransformation.transformation()); -+ this.initializeRotationDirections(); // Paper ++ this.initializeRotationDirections(); // Paper - Avoid Lazy Initialization for Enum Fields } private BooleanList packInversions() { @@ -23,7 +23,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - public Direction rotate(Direction direction) { -+ public void initializeRotationDirections() { // Paper ++ public void initializeRotationDirections() { // Paper - Avoid Lazy Initialization for Enum Fields if (this.rotatedDirections == null) { this.rotatedDirections = Maps.newEnumMap(Direction.class); Direction.Axis[] axiss = Direction.Axis.values(); @@ -31,10 +31,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } -+ // Paper start - Move lazy initialization to constructor ++ // Paper start - Avoid Lazy Initialization for Enum Fields + } + public Direction rotate(Direction direction) { -+ // Paper end ++ // Paper end - Avoid Lazy Initialization for Enum Fields return this.rotatedDirections.get(direction); } diff --git a/patches/server/Call-missing-BlockDispenseEvent.patch b/patches/server/Call-missing-BlockDispenseEvent.patch index aaddedbaa8..49b15be6d2 100644 --- a/patches/server/Call-missing-BlockDispenseEvent.patch +++ b/patches/server/Call-missing-BlockDispenseEvent.patch @@ -12,13 +12,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.setSuccess(true); if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) { if ((Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) != 4) { -+ // Paper start ++ // Paper start - Call missing BlockDispenseEvent + ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition, stack, this); + if (result != null) { + this.setSuccess(false); + return result; + } -+ // Paper end ++ // Paper end - Call missing BlockDispenseEvent RespawnAnchorBlock.charge((Entity) null, worldserver, blockposition, iblockdata); stack.shrink(1); } else { @@ -26,13 +26,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Optional optional = HoneycombItem.getWaxed(iblockdata); if (optional.isPresent()) { -+ // Paper start ++ // Paper start - Call missing BlockDispenseEvent + ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition, stack, this); + if (result != null) { + this.setSuccess(false); + return result; + } -+ // Paper end ++ // Paper end - Call missing BlockDispenseEvent worldserver.setBlockAndUpdate(blockposition, (BlockState) optional.get()); worldserver.levelEvent(3003, blockposition, 0); stack.shrink(1); @@ -40,12 +40,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (!worldserver.getBlockState(blockposition1).is(BlockTags.CONVERTABLE_TO_MUD)) { return this.defaultDispenseItemBehavior.dispense(pointer, stack); } else { -+ // Paper start ++ // Paper start - Call missing BlockDispenseEvent + ItemStack result = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDispenseEvent(pointer, blockposition1, stack, this); + if (result != null) { + return result; + } -+ // Paper end ++ // Paper end - Call missing BlockDispenseEvent if (!worldserver.isClientSide) { for (int k = 0; k < 5; ++k) { worldserver.sendParticles(ParticleTypes.SPLASH, (double) blockposition.getX() + worldserver.random.nextDouble(), (double) (blockposition.getY() + 1), (double) blockposition.getZ() + worldserver.random.nextDouble(), 1, 0.0D, 0.0D, 0.0D, 1.0D); @@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } // Paper end -+ // Paper start - missing BlockDispenseEvent calls ++ // Paper start - Call missing BlockDispenseEvent + @Nullable + public static ItemStack handleBlockDispenseEvent(net.minecraft.core.dispenser.BlockSource pointer, BlockPos to, ItemStack itemStack, net.minecraft.core.dispenser.DispenseItemBehavior instance) { + org.bukkit.block.Block bukkitBlock = pointer.level().getWorld().getBlockAt(pointer.pos().getX(), pointer.pos().getY(), pointer.pos().getZ()); @@ -81,7 +81,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + return null; + } -+ // Paper end - missing BlockDispenseEvent calls ++ // Paper end - Call missing BlockDispenseEvent + // Paper start - add EntityFertilizeEggEvent /** diff --git a/patches/server/Don-t-enforce-icanhasbukkit-default-if-alias-block-e.patch b/patches/server/Don-t-enforce-icanhasbukkit-default-if-alias-block-e.patch index 3f28e7a50c..df87b8f243 100644 --- a/patches/server/Don-t-enforce-icanhasbukkit-default-if-alias-block-e.patch +++ b/patches/server/Don-t-enforce-icanhasbukkit-default-if-alias-block-e.patch @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final YamlConfiguration commandsDefaults = YamlConfiguration.loadConfiguration(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("configurations/commands.yml"), Charsets.UTF_8)); + if (this.commandsConfiguration.contains("aliases")) commandsDefaults.set("aliases", null); + this.commandsConfiguration.setDefaults(commandsDefaults); -+ // Paper stop - dont enforce icanhasbukkit default if alias block exists ++ // Paper stop - don't enforce icanhasbukkit default if alias block exists this.saveCommandsConfig(); // Migrate aliases from old file and add previously implicit $1- to pass all arguments diff --git a/patches/server/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch b/patches/server/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch index a9ffa9551c..623ad9dcd4 100644 --- a/patches/server/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch +++ b/patches/server/Don-t-lookup-game-profiles-that-have-no-UUID-and-no-.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } }; -+ if (!org.apache.commons.lang3.StringUtils.isBlank(name)) // Paper - Don't lookup a profile with a blank name) ++ if (!org.apache.commons.lang3.StringUtils.isBlank(name)) // Paper - Don't lookup a profile with a blank name repository.findProfilesByNames(new String[]{name}, profilelookupcallback); GameProfile gameprofile = (GameProfile) atomicreference.get(); diff --git a/patches/server/Expand-PlayerItemMendEvent.patch b/patches/server/Expand-PlayerItemMendEvent.patch index f702fcad3f..ae1c525eb9 100644 --- a/patches/server/Expand-PlayerItemMendEvent.patch +++ b/patches/server/Expand-PlayerItemMendEvent.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 int j = Math.min(this.xpToDurability(amount), itemstack.getDamageValue()); // CraftBukkit start - org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j); -+ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j, this::durabilityToXp); // Paper ++ org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, this, itemstack, entry.getKey(), j, this::durabilityToXp); // Paper - Expand PlayerItemMendEvent j = event.getRepairAmount(); if (event.isCancelled()) { return amount; @@ -22,13 +22,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 itemstack.setDamageValue(itemstack.getDamageValue() - j); - int k = amount - this.durabilityToXp(j); -+ int k = amount - event.getDurabilityToXpOperation().applyAsInt(j); // Paper ++ int k = amount - event.getDurabilityToXpOperation().applyAsInt(j); // Paper - Expand PlayerItemMendEvent this.value = k; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls -+ // Paper start ++ // Paper start - Expand PlayerItemMendEvent + if (j == 0 && amount == k) { // if repair amount is 0 and no xp was removed, don't do recursion; treat as cancelled + return k; + } -+ // Paper end ++ // Paper end - Expand PlayerItemMendEvent return k > 0 ? this.repairPlayerItems(player, k) : 0; } else { @@ -41,12 +41,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 int i = Math.min(orb.xpToDurability(amount), itemstack.getDamageValue()); - org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, stackEntry.getKey(), i); -+ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, stackEntry.getKey(), i, orb::durabilityToXp); // Paper ++ org.bukkit.event.player.PlayerItemMendEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerItemMendEvent(handle, orb, itemstack, stackEntry.getKey(), i, orb::durabilityToXp); // Paper - Expand PlayerItemMendEvent i = event.getRepairAmount(); orb.discard(); if (!event.isCancelled()) { - amount -= orb.durabilityToXp(i); -+ amount -= event.getDurabilityToXpOperation().applyAsInt(i); // Paper ++ amount -= event.getDurabilityToXpOperation().applyAsInt(i); // Paper - Expand PlayerItemMendEvent itemstack.setDamageValue(itemstack.getDamageValue() - i); } } @@ -59,11 +59,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - public static PlayerItemMendEvent callPlayerItemMendEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb orb, net.minecraft.world.item.ItemStack nmsMendedItem, net.minecraft.world.entity.EquipmentSlot slot, int repairAmount) { -+ public static PlayerItemMendEvent callPlayerItemMendEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb orb, net.minecraft.world.item.ItemStack nmsMendedItem, net.minecraft.world.entity.EquipmentSlot slot, int repairAmount, java.util.function.IntUnaryOperator durabilityToXpOp) { // Paper ++ public static PlayerItemMendEvent callPlayerItemMendEvent(net.minecraft.world.entity.player.Player entity, net.minecraft.world.entity.ExperienceOrb orb, net.minecraft.world.item.ItemStack nmsMendedItem, net.minecraft.world.entity.EquipmentSlot slot, int repairAmount, java.util.function.IntUnaryOperator durabilityToXpOp) { // Paper - Expand PlayerItemMendEvent Player player = (Player) entity.getBukkitEntity(); org.bukkit.inventory.ItemStack bukkitStack = CraftItemStack.asCraftMirror(nmsMendedItem); - PlayerItemMendEvent event = new PlayerItemMendEvent(player, bukkitStack, CraftEquipmentSlot.getSlot(slot), (ExperienceOrb) orb.getBukkitEntity(), repairAmount); -+ PlayerItemMendEvent event = new PlayerItemMendEvent(player, bukkitStack, CraftEquipmentSlot.getSlot(slot), (ExperienceOrb) orb.getBukkitEntity(), repairAmount, durabilityToXpOp); // Paper ++ PlayerItemMendEvent event = new PlayerItemMendEvent(player, bukkitStack, CraftEquipmentSlot.getSlot(slot), (ExperienceOrb) orb.getBukkitEntity(), repairAmount, durabilityToXpOp); // Paper - Expand PlayerItemMendEvent Bukkit.getPluginManager().callEvent(event); return event; } diff --git a/patches/server/Fix-DamageCause-for-Falling-Blocks.patch b/patches/server/Fix-DamageCause-for-Falling-Blocks.patch index d8d2bd9fda..01cdf18b46 100644 --- a/patches/server/Fix-DamageCause-for-Falling-Blocks.patch +++ b/patches/server/Fix-DamageCause-for-Falling-Blocks.patch @@ -12,11 +12,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } else if (source.is(DamageTypes.SONIC_BOOM)) { cause = DamageCause.SONIC_BOOM; } -+ // Paper start - fix handle of Falling Blocks ++ // Paper start - fix falling block handling + else if (source.is(DamageTypes.FALLING_STALACTITE) || source.is(DamageTypes.FALLING_BLOCK) || source.is(DamageTypes.FALLING_ANVIL)) { + cause = DamageCause.FALLING_BLOCK; + } -+ // Paper end ++ // Paper end - fix falling block handling return CraftEventFactory.callEntityDamageEvent(damager, entity, cause, modifiers, modifierFunctions, cancelled, source.isCritical()); // Paper - add critical damage API } else if (source.is(DamageTypes.FELL_OUT_OF_WORLD)) { diff --git a/patches/server/Fix-HumanEntity-drop-not-updating-the-client-inv.patch b/patches/server/Fix-HumanEntity-drop-not-updating-the-client-inv.patch index 3a1cebf342..82446440ff 100644 --- a/patches/server/Fix-HumanEntity-drop-not-updating-the-client-inv.patch +++ b/patches/server/Fix-HumanEntity-drop-not-updating-the-client-inv.patch @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean dropItem(boolean dropAll) { - if (!(this.getHandle() instanceof ServerPlayer)) return false; - return ((ServerPlayer) this.getHandle()).drop(dropAll); -+ // Paper start - notify client of remote slot change ++ // Paper start - Fix HumanEntity#drop not updating the client inv + if (!(this.getHandle() instanceof ServerPlayer player)) return false; + boolean success = player.drop(dropAll); + if (!success) return false; @@ -24,7 +24,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final java.util.OptionalInt optionalSlot = player.containerMenu.findSlot(inv, inv.selected); + optionalSlot.ifPresent(slot -> player.containerSynchronizer.sendSlotChange(player.containerMenu, slot, inv.getSelected())); + return true; -+ // Paper end ++ // Paper end - Fix HumanEntity#drop not updating the client inv } @Override diff --git a/patches/server/Fix-beehives-generating-from-using-bonemeal.patch b/patches/server/Fix-beehives-generating-from-using-bonemeal.patch index 05bdada235..08c0ee2b05 100644 --- a/patches/server/Fix-beehives-generating-from-using-bonemeal.patch +++ b/patches/server/Fix-beehives-generating-from-using-bonemeal.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } for (CraftBlockState blockstate : blocks) { world.setBlock(blockstate.getPosition(),blockstate.getHandle(), blockstate.getFlag()); // SPIGOT-7248 - manual update to avoid physics where appropriate -+ if (blockstate instanceof org.bukkit.craftbukkit.block.CapturedBlockState capturedBlockState) capturedBlockState.checkTreeBlockHack(); // Paper ++ if (blockstate instanceof org.bukkit.craftbukkit.block.CapturedBlockState capturedBlockState) capturedBlockState.checkTreeBlockHack(); // Paper - Fix beehives generating from using bonemeal } entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat } @@ -24,12 +24,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean update(boolean force, boolean applyPhysics) { boolean result = super.update(force, applyPhysics); -+ // Paper start ++ // Paper start - Fix beehives generating from using bonemeal + this.checkTreeBlockHack(); + return result; + } + public void checkTreeBlockHack() { -+ // Paper end ++ // Paper end - Fix beehives generating from using bonemeal // SPIGOT-5537: Horrible hack to manually add bees given World.captureTreeGeneration does not support tiles if (this.treeBlock && this.getType() == Material.BEE_NEST) { WorldGenLevel generatoraccessseed = this.world.getHandle(); @@ -38,7 +38,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - return result; -+ // Paper ++ // Paper - Fix beehives generating from using bonemeal } @Override diff --git a/patches/server/Fix-block-place-logic.patch b/patches/server/Fix-block-place-logic.patch index 70fa38293e..41b238568c 100644 --- a/patches/server/Fix-block-place-logic.patch +++ b/patches/server/Fix-block-place-logic.patch @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 SoundType soundeffecttype = iblockdata1.getSoundType(); - // world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), SoundCategory.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); -+ if (entityhuman == null) world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), net.minecraft.sounds.SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); // Paper - reintroduce this for the dispenser (i.e the shulker) ++ if (entityhuman == null) world.playSound(entityhuman, blockposition, this.getPlaceSound(iblockdata1), net.minecraft.sounds.SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); // Paper - Fix block place logic; reintroduce this for the dispenser (i.e the shulker) world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(entityhuman, iblockdata1)); if ((entityhuman == null || !entityhuman.getAbilities().instabuild) && itemstack != ItemStack.EMPTY) { // CraftBukkit itemstack.shrink(1); @@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - } - - tileentityjukebox.setTheItem(record); -+ tileentityjukebox.setTheItem(this.copy()); // Paper - sync this with record item, jukebox has now an inventory ++ tileentityjukebox.setTheItem(this.copy()); // Paper - Fix block place logic; sync this with record item, jukebox has now an inventory world.gameEvent(GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entityhuman, world.getBlockState(blockposition))); } @@ -48,7 +48,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start iblockdata1.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); // Don't call an event for the old block to limit event spam CraftWorld world = ((ServerLevel) this).getWorld(); -+ boolean cancelledUpdates = false; // Paper ++ boolean cancelledUpdates = false; // Paper - Fix block place logic if (world != null && ((ServerLevel)this).hasPhysicsEvent) { // Paper BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()), CraftBlockData.fromData(iblockdata)); this.getCraftServer().getPluginManager().callEvent(event); @@ -56,13 +56,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - if (event.isCancelled()) { - return; - } -+ cancelledUpdates = event.isCancelled(); // Paper ++ cancelledUpdates = event.isCancelled(); // Paper - Fix block place logic } // CraftBukkit end -+ if (!cancelledUpdates) { // Paper ++ if (!cancelledUpdates) { // Paper - Fix block place logic iblockdata.updateNeighbourShapes(this, blockposition, k, j - 1); iblockdata.updateIndirectNeighbourShapes(this, blockposition, k, j - 1); -+ } // Paper ++ } // Paper - Fix block place logic } // CraftBukkit start - SPIGOT-5710 diff --git a/patches/server/Fix-cmd-permission-levels-for-command-blocks.patch b/patches/server/Fix-cmd-permission-levels-for-command-blocks.patch index ab3cbd17a4..94d9ad3a35 100644 --- a/patches/server/Fix-cmd-permission-levels-for-command-blocks.patch +++ b/patches/server/Fix-cmd-permission-levels-for-command-blocks.patch @@ -12,17 +12,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return this.permissionLevel >= level; } -+ // Paper start ++ // Paper start - Fix permission levels for command blocks + private boolean forceRespectPermissionLevel() { + return this.source == CommandSource.NULL || (this.source instanceof final net.minecraft.world.level.BaseCommandBlock commandBlock && commandBlock.getLevel().paperConfig().commandBlocks.forceFollowPermLevel); + } -+ // Paper end ++ // Paper end - Fix permission levels for command blocks + // CraftBukkit start public boolean hasPermission(int i, String bukkitPermission) { - // World is null when loading functions - return ((this.getLevel() == null || !this.getLevel().getCraftServer().ignoreVanillaPermissions) && this.permissionLevel >= i) || this.getBukkitSender().hasPermission(bukkitPermission); -+ // Paper start ++ // Paper start - Fix permission levels for command blocks + final java.util.function.BooleanSupplier hasBukkitPerm = () -> this.source == CommandSource.NULL /*treat NULL as having all bukkit perms*/ || this.getBukkitSender().hasPermission(bukkitPermission); // lazily check bukkit perms to the benefit of custom permission setups + // if the server is null, we must check the vanilla perm level system + // if ignoreVanillaPermissions is true, we can skip vanilla perms and just run the bukkit perm check @@ -36,7 +36,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + return hasBukkitPerm.getAsBoolean(); -+ // Paper end ++ // Paper end - Fix permission levels for command blocks } // CraftBukkit end @@ -58,7 +58,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - || cmd.equalsIgnoreCase("pardon") || cmd.equalsIgnoreCase("pardon-ip") || cmd.equalsIgnoreCase("reload")) { - return; - } -+ // Paper - use proper permission levels to block these commands ++ // Paper - Fix permission levels for command blocks // Handle vanilla commands; if (sender.getLevel().getCraftServer().getCommandBlockOverride(args[0])) { diff --git a/patches/server/Fix-certain-inventories-returning-null-Locations.patch b/patches/server/Fix-inventories-returning-null-Locations.patch similarity index 88% rename from patches/server/Fix-certain-inventories-returning-null-Locations.patch rename to patches/server/Fix-inventories-returning-null-Locations.patch index 2a5f2d6b72..5659c35908 100644 --- a/patches/server/Fix-certain-inventories-returning-null-Locations.patch +++ b/patches/server/Fix-inventories-returning-null-Locations.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Wed, 15 Mar 2023 18:29:45 -0700 -Subject: [PATCH] Fix certain inventories returning null Locations +Subject: [PATCH] Fix inventories returning null Locations Wandering Trader, AbstractHorse, Beacon and Composter inventories returned null locations when a block or entity location is readily available @@ -16,7 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Location getLocation() { -+ // Paper start ++ // Paper start - Fix inventories returning null Locations + // When the block inventory does not have a tile state that implements getLocation, e. g. composters + if (this.bukkitOwner instanceof org.bukkit.inventory.BlockInventoryHolder blockInventoryHolder) { + return blockInventoryHolder.getBlock().getLocation(); @@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (this.bukkitOwner instanceof org.bukkit.entity.Entity entity) { + return entity.getLocation(); + } -+ // Paper end ++ // Paper end - Fix inventories returning null Locations return null; } @@ -37,12 +37,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public int getMaxStackSize() { return 1; } -+ // Paper start ++ // Paper start - Fix inventories returning null Locations + @Override + public org.bukkit.Location getLocation() { + return context.getLocation(); + } -+ // Paper end ++ // Paper end - Fix inventories returning null Locations }; checkContainerDataCount(propertyDelegate, 3); this.beaconData = propertyDelegate; @@ -55,7 +55,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public Location getLocation() { - return (this.merchant instanceof Villager) ? ((Villager) this.merchant).getBukkitEntity().getLocation() : null; -+ return (this.merchant instanceof AbstractVillager) ? ((AbstractVillager) this.merchant).getBukkitEntity().getLocation() : null; // Paper ++ return (this.merchant instanceof AbstractVillager) ? ((AbstractVillager) this.merchant).getBukkitEntity().getLocation() : null; // Paper - Fix inventories returning null Locations } // CraftBukkit end diff --git a/patches/server/Fix-spigot-sound-playing-for-BlockItem-ItemStacks.patch b/patches/server/Fix-spigot-sound-playing-for-BlockItem-ItemStacks.patch index 3c0ccaceb7..b11e629eb7 100644 --- a/patches/server/Fix-spigot-sound-playing-for-BlockItem-ItemStacks.patch +++ b/patches/server/Fix-spigot-sound-playing-for-BlockItem-ItemStacks.patch @@ -13,11 +13,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // SPIGOT-1288 - play sound stripped from ItemBlock if (this.item instanceof BlockItem) { - SoundType soundeffecttype = ((BlockItem) this.item).getBlock().defaultBlockState().getSoundType(); // TODO: not strictly correct, however currently only affects decorated pots -+ // Paper start ++ // Paper start - Fix spigot sound playing for BlockItem ItemStacks + BlockPos position = new net.minecraft.world.item.context.BlockPlaceContext(context).getClickedPos(); + net.minecraft.world.level.block.state.BlockState blockData = world.getBlockState(position); + SoundType soundeffecttype = blockData.getSoundType(); -+ // Paper end ++ // Paper end - Fix spigot sound playing for BlockItem ItemStacks world.playSound(entityhuman, blockposition, soundeffecttype.getPlaceSound(), SoundSource.BLOCKS, (soundeffecttype.getVolume() + 1.0F) / 2.0F, soundeffecttype.getPitch() * 0.8F); } diff --git a/patches/server/Fix-text-display-error-on-spawn.patch b/patches/server/Fix-text-display-error-on-spawn.patch index 5a6d5ded24..766604b708 100644 --- a/patches/server/Fix-text-display-error-on-spawn.patch +++ b/patches/server/Fix-text-display-error-on-spawn.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 b = loadFlag(b, nbt, "see_through", (byte)2); b = loadFlag(b, nbt, "default_background", (byte)4); - Optional optional = Display.TextDisplay.Align.CODEC.decode(NbtOps.INSTANCE, nbt.get("alignment")).resultOrPartial(Util.prefix("Display entity", Display.LOGGER::error)).map(Pair::getFirst); -+ Optional optional = Display.TextDisplay.Align.CODEC.decode(NbtOps.INSTANCE, nbt.get("alignment")).result().map(Pair::getFirst); // Paper - hide error message ++ Optional optional = Display.TextDisplay.Align.CODEC.decode(NbtOps.INSTANCE, nbt.get("alignment")).result().map(Pair::getFirst); // Paper - Hide text display error on spawn if (optional.isPresent()) { byte var10000; switch ((Display.TextDisplay.Align)optional.get()) { diff --git a/patches/server/Lag-compensation-ticks.patch b/patches/server/Lag-compensation-ticks.patch index 89d9c2f46a..6ac8115a98 100644 --- a/patches/server/Lag-compensation-ticks.patch +++ b/patches/server/Lag-compensation-ticks.patch @@ -27,7 +27,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 ServerLevel worldserver = (ServerLevel) iterator.next(); + worldserver.updateLagCompensationTick(); // Paper - lag compensation worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper + net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 @@ -71,7 +71,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { this.getEntityData().resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer); } - // Paper end + // Paper end - Properly cancel usable items + // Paper start - lag compensate eating + protected long eatStartTime; + protected int totalEatTimeTicks; diff --git a/patches/server/Only-capture-actual-tree-growth.patch b/patches/server/Only-capture-actual-tree-growth.patch index a6c44e0758..dcc13f51b8 100644 --- a/patches/server/Only-capture-actual-tree-growth.patch +++ b/patches/server/Only-capture-actual-tree-growth.patch @@ -25,7 +25,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 for (CraftBlockState blockstate : blocks) { world.setBlock(blockstate.getPosition(),blockstate.getHandle(), blockstate.getFlag()); // SPIGOT-7248 - manual update to avoid physics where appropriate + world.checkCapturedTreeStateForObserverNotify(blockposition, blockstate); // Paper - notify observers even if grow failed - if (blockstate instanceof org.bukkit.craftbukkit.block.CapturedBlockState capturedBlockState) capturedBlockState.checkTreeBlockHack(); // Paper + if (blockstate instanceof org.bukkit.craftbukkit.block.CapturedBlockState capturedBlockState) capturedBlockState.checkTreeBlockHack(); // Paper - Fix beehives generating from using bonemeal } entityhuman.awardStat(Stats.ITEM_USED.get(item)); // SPIGOT-7236 - award stat diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java diff --git a/patches/server/Only-tick-item-frames-if-players-can-see-it.patch b/patches/server/Only-tick-item-frames-if-players-can-see-it.patch index 954ca7c6aa..29acf8973b 100644 --- a/patches/server/Only-tick-item-frames-if-players-can-see-it.patch +++ b/patches/server/Only-tick-item-frames-if-players-can-see-it.patch @@ -14,7 +14,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Entity entity = this.entity; - if (entity instanceof ItemFrame) { -+ if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame) { // Paper - Only tick item frames if players can see it ++ if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame) { // Paper - Perf: Only tick item frames if players can see it ItemFrame entityitemframe = (ItemFrame) entity; if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block diff --git a/patches/server/Optimize-Hoppers.patch b/patches/server/Optimize-Hoppers.patch index d871b6d2ae..8aa716b517 100644 --- a/patches/server/Optimize-Hoppers.patch +++ b/patches/server/Optimize-Hoppers.patch @@ -57,7 +57,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 while (iterator.hasNext()) { ServerLevel worldserver = (ServerLevel) iterator.next(); worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper -+ net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper ++ net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper this.profiler.push(() -> { @@ -70,17 +70,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public ItemStack copy() { - if (this.isEmpty()) { -+ // Paper start ++ // Paper start - Perf: Optimize Hoppers + return this.copy(false); + } + + public ItemStack copy(boolean originalItem) { + if (!originalItem && this.isEmpty()) { -+ // Paper end ++ // Paper end - Perf: Optimize Hoppers return ItemStack.EMPTY; } else { - ItemStack itemstack = new ItemStack(this.getItem(), this.count); -+ ItemStack itemstack = new ItemStack(originalItem ? this.item : this.getItem(), this.count); // Paper ++ ItemStack itemstack = new ItemStack(originalItem ? this.item : this.getItem(), this.count); // Paper - Perf: Optimize Hoppers itemstack.setPopTime(this.getPopTime()); if (this.tag != null) { @@ -92,7 +92,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import co.aikar.timings.Timing; // Paper public abstract class BlockEntity { -+ static boolean ignoreTileUpdates; // Paper ++ static boolean ignoreTileUpdates; // Paper - Perf: Optimize Hoppers public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper // CraftBukkit start - data containers @@ -100,7 +100,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void setChanged() { if (this.level != null) { -+ if (ignoreTileUpdates) return; // Paper ++ if (ignoreTileUpdates) return; // Paper - Perf: Optimize Hoppers BlockEntity.setChanged(this.level, this.worldPosition, this.blockState); } @@ -112,7 +112,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } -+ // Paper start - optimize hoppers ++ // Paper start - Perf: Optimize Hoppers + private static final int HOPPER_EMPTY = 0; + private static final int HOPPER_HAS_ITEMS = 1; + private static final int HOPPER_IS_FULL = 2; @@ -147,7 +147,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + return empty ? HOPPER_EMPTY : (full ? HOPPER_IS_FULL : HOPPER_HAS_ITEMS); + } -+ // Paper end - optimize hoppers ++ // Paper end - Perf: Optimize Hoppers + private static boolean tryMoveItems(Level world, BlockPos pos, BlockState state, HopperBlockEntity blockEntity, BooleanSupplier booleansupplier) { if (world.isClientSide) { @@ -157,14 +157,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 boolean flag = false; - if (!blockEntity.isEmpty()) { -+ int fullState = getFullState(blockEntity); // Paper - optimize hoppers ++ int fullState = getFullState(blockEntity); // Paper - Perf: Optimize Hoppers + -+ if (fullState != HOPPER_EMPTY) { // Paper - optimize hoppers ++ if (fullState != HOPPER_EMPTY) { // Paper - Perf: Optimize Hopperss flag = HopperBlockEntity.ejectItems(world, pos, state, (Container) blockEntity, blockEntity); // CraftBukkit } - if (!blockEntity.inventoryFull()) { -+ if (fullState != HOPPER_IS_FULL || flag) { // Paper - optimize hoppers ++ if (fullState != HOPPER_IS_FULL || flag) { // Paper - Perf: Optimize Hoppers flag |= booleansupplier.getAsBoolean(); } @@ -172,7 +172,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return false; } -+ // Paper start - Optimize Hoppers ++ // Paper start - Perf: Optimize Hoppers + private static boolean skipPullModeEventFire; + private static boolean skipPushModeEventFire; + public static boolean skipHopperEvents; @@ -366,7 +366,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + private static final java.util.function.BiPredicate STACK_SIZE_TEST = (itemstack, i) -> itemstack.getCount() >= itemstack.getMaxStackSize(); + private static final java.util.function.BiPredicate IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty(); -+ // Paper end ++ // Paper end - Perf: Optimize Hoppers + private static boolean ejectItems(Level world, BlockPos blockposition, BlockState iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit Container iinventory1 = HopperBlockEntity.getAttachedContainer(world, blockposition, iblockdata); @@ -453,7 +453,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - return false; + // return false; -+ // Paper end ++ // Paper end - Perf: Optimize Hoppers } } } @@ -466,7 +466,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - - return itemstack.getCount() >= itemstack.getMaxStackSize(); - }); -+ // Paper start - optimize hoppers ++ // Paper start - Perf: Optimize Hoppers + if (inventory instanceof WorldlyContainer worldlyContainer) { + for (final int slot : worldlyContainer.getSlotsForFace(direction)) { + final ItemStack stack = inventory.getItem(slot); @@ -484,14 +484,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + return true; + } -+ // Paper end - optimize hoppers ++ // Paper end - Perf: Optimize Hoppers } private static boolean isEmptyContainer(Container inv, Direction facing) { - return HopperBlockEntity.getSlots(inv, facing).allMatch((i) -> { - return inv.getItem(i).isEmpty(); - }); -+ return allMatch(inv, facing, IS_EMPTY_TEST); ++ return allMatch(inv, facing, IS_EMPTY_TEST); // Paper - Perf: Optimize Hoppers } public static boolean suckInItems(Level world, Hopper hopper) { @@ -502,7 +502,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - return HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) ? false : HopperBlockEntity.getSlots(iinventory, enumdirection).anyMatch((i) -> { - return HopperBlockEntity.a(hopper, iinventory, i, enumdirection, world); // Spigot - }); -+ // Paper start - optimize hoppers and remove streams ++ // Paper start - Perf: Optimize Hoppers + skipPullModeEventFire = skipHopperEvents; + // merge container isEmpty check and move logic into one loop + if (iinventory instanceof WorldlyContainer worldlyContainer) { @@ -528,7 +528,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + return false; + } -+ // Paper end ++ // Paper end - Perf: Optimize Hoppers } else { Iterator iterator = HopperBlockEntity.getItemsAtAndAbove(world, hopper).iterator(); @@ -579,7 +579,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - - itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot - iinventory.setItem(i, itemstack1); -+ // Paper start - replace pull logic; MAKE SURE TO CHECK FOR DIFFS WHEN UPDATING ++ // Paper start - Perf: Optimize Hoppers; replace pull logic; MAKE SURE TO CHECK FOR DIFFS WHEN UPDATING + if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(ihopper, iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left unused incase reflective plugins + return hopperPull(world, ihopper, iinventory, itemstack, i); + // ItemStack itemstack1 = itemstack.copy(); @@ -620,7 +620,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot + // iinventory.setItem(i, itemstack1); -+ // Paper end ++ // Paper end - Perf: Optimize Hoppers } return false; @@ -630,13 +630,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit start - InventoryPickupItemEvent event = new InventoryPickupItemEvent(inventory.getOwner().getInventory(), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); + if (InventoryPickupItemEvent.getHandlerList().getRegisteredListeners().length > 0) { // Paper - optimize hoppers -+ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(inventory), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); // Paper - use getInventory() to avoid snapshot creation ++ InventoryPickupItemEvent event = new InventoryPickupItemEvent(getInventory(inventory), (org.bukkit.entity.Item) itemEntity.getBukkitEntity()); // Paper - Perf: Optimize Hoppers; use getInventory() to avoid snapshot creation itemEntity.level().getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return false; } // CraftBukkit end -+ } // Paper - optimize hoppers ++ } // Paper - Perf: Optimize Hoppers ItemStack itemstack = itemEntity.getItem().copy(); ItemStack itemstack1 = HopperBlockEntity.addItem((Container) null, inventory, itemstack, (Direction) null); @@ -644,9 +644,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 stack = stack.split(to.getMaxStackSize()); } // Spigot end -+ ignoreTileUpdates = true; // Paper ++ ignoreTileUpdates = true; // Paper - Perf: Optimize Hoppers to.setItem(slot, stack); -+ ignoreTileUpdates = false; // Paper ++ ignoreTileUpdates = false; // Paper - Perf: Optimize Hoppers stack = leftover; // Paper flag = true; } else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) { @@ -654,16 +654,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit end } -+ // Paper start - optimize hopper item suck in ++ // Paper start - Perf: Optimize Hoppers + static final AABB HOPPER_ITEM_SUCK_OVERALL = Hopper.SUCK.bounds(); + static final AABB[] HOPPER_ITEM_SUCK_INDIVIDUAL = Hopper.SUCK.toAabbs().toArray(new AABB[0]); -+ // Paper end - optimize hopper item suck in ++ // Paper end - Perf: Optimize Hoppers + public static List getItemsAtAndAbove(Level world, Hopper hopper) { - return (List) hopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> { - return world.getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(hopper.getLevelX() - 0.5D, hopper.getLevelY() - 0.5D, hopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream(); - }).collect(Collectors.toList()); -+ // Paper start - optimize hopper item suck in ++ // Paper start - Perf: Optimize Hoppers + // eliminate multiple getEntitiesOfClass() but maintain the voxelshape collision by moving + // the individual AABB checks into the predicate + final double shiftX = hopper.getLevelX() - 0.5D; @@ -682,23 +682,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + return false; + }); -+ // Paper end - optimize hopper item suck in ++ // Paper end - Perf: Optimize Hoppers } @Nullable public static Container getContainerAt(Level world, BlockPos pos) { - return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D); -+ return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, true); // Paper ++ return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, true); // Paper - Perf: Optimize Hoppers } @Nullable private static Container getContainerAt(Level world, double x, double y, double z) { -+ // Paper start - add optimizeEntities parameter ++ // Paper start - Perf: Optimize Hoppers + return HopperBlockEntity.getContainerAt(world, x, y, z, false); + } + @Nullable + private static Container getContainerAt(Level world, double x, double y, double z, final boolean optimizeEntities) { -+ // Paper end - add optimizeEntities parameter ++ // Paper end - Perf: Optimize Hoppers Object object = null; BlockPos blockposition = BlockPos.containing(x, y, z); if ( !world.spigotConfig.hopperCanLoadChunks && !world.hasChunkAt( blockposition ) ) return null; // Spigot @@ -708,8 +708,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - if (object == null) { - List list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); -+ if (object == null && (!optimizeEntities || !world.paperConfig().hopper.ignoreOccludingBlocks || !iblockdata.getBukkitMaterial().isOccluding())) { // Paper -+ List list = world.getEntitiesOfClass((Class)Container.class, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); // Paper - optimize hoppers, use getEntitiesOfClass ++ if (object == null && (!optimizeEntities || !world.paperConfig().hopper.ignoreOccludingBlocks || !iblockdata.getBukkitMaterial().isOccluding())) { // Paper - Perf: Optimize Hoppers ++ List list = world.getEntitiesOfClass((Class)Container.class, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); // Paper - Perf: Optimize Hoppers if (!list.isEmpty()) { object = (Container) list.get(world.random.nextInt(list.size())); @@ -718,7 +718,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private static boolean canMergeItems(ItemStack first, ItemStack second) { - return first.getCount() <= first.getMaxStackSize() && ItemStack.isSameItemSameTags(first, second); -+ return first.getCount() < first.getMaxStackSize() && first.is(second.getItem()) && first.getDamageValue() == second.getDamageValue() && ((first.isEmpty() && second.isEmpty()) || java.util.Objects.equals(first.getTag(), second.getTag())); // Paper - used to return true for full itemstacks?! ++ return first.getCount() < first.getMaxStackSize() && first.is(second.getItem()) && first.getDamageValue() == second.getDamageValue() && ((first.isEmpty() && second.isEmpty()) || java.util.Objects.equals(first.getTag(), second.getTag())); // Paper - Perf: Optimize Hoppers; used to return true for full itemstacks?! } @Override @@ -731,20 +731,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean isEmpty() { this.unpackLootTable((Player)null); - return this.getItems().stream().allMatch(ItemStack::isEmpty); -+ // Paper start ++ // Paper start - Perf: Optimize Hoppers + for (final ItemStack itemStack : this.getItems()) { + if (!itemStack.isEmpty()) { + return false; + } + } + return true; -+ // Paper end ++ // Paper end - Perf: Optimize Hoppers } @Override public ItemStack getItem(int slot) { - this.unpackLootTable((Player)null); -+ if (slot == 0) this.unpackLootTable((Player)null); // Paper ++ if (slot == 0) this.unpackLootTable((Player) null); // Paper - Perf: Optimize Hoppers return this.getItems().get(slot); } diff --git a/patches/server/Prevent-GameEvents-being-fired-from-unloaded-chunks.patch b/patches/server/Prevent-GameEvents-being-fired-from-unloaded-chunks.patch index 453dddc5bd..58e30ef1d1 100644 --- a/patches/server/Prevent-GameEvents-being-fired-from-unloaded-chunks.patch +++ b/patches/server/Prevent-GameEvents-being-fired-from-unloaded-chunks.patch @@ -12,11 +12,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public void gameEvent(GameEvent event, Vec3 emitterPos, GameEvent.Context emitter) { -+ // Paper start ++ // Paper start - Prevent GameEvents being fired from unloaded chunks + if (this.getChunkIfLoadedImmediately((Mth.floor(emitterPos.x) >> 4), (Mth.floor(emitterPos.z) >> 4)) == null) { + return; + } -+ // Paper end ++ // Paper end - Prevent GameEvents being fired from unloaded chunks this.gameEventDispatcher.post(event, emitterPos, emitter); } diff --git a/patches/server/Prevent-causing-expired-keys-from-impacting-new-join.patch b/patches/server/Prevent-causing-expired-keys-from-impacting-new-join.patch index a81e432950..a71d4a8a18 100644 --- a/patches/server/Prevent-causing-expired-keys-from-impacting-new-join.patch +++ b/patches/server/Prevent-causing-expired-keys-from-impacting-new-join.patch @@ -13,13 +13,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 serialized.chatSession = buf.readNullable(RemoteChatSession.Data::read); }, (buf, entry) -> { - buf.writeNullable(entry.chatSession, RemoteChatSession.Data::write); -+ // Paper start ++ // Paper start - Prevent causing expired keys from impacting new joins + RemoteChatSession.Data chatSession = entry.chatSession; + if (chatSession != null && chatSession.profilePublicKey().hasExpired()) { + chatSession = null; + } + buf.writeNullable(chatSession, RemoteChatSession.Data::write); -+ // Paper end ++ // Paper end - Prevent causing expired keys from impacting new joins }), UPDATE_GAME_MODE((serialized, buf) -> { serialized.gameMode = GameType.byId(buf.readVarInt()); @@ -31,7 +31,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private int knownMovePacketCount; @Nullable private RemoteChatSession chatSession; -+ private boolean hasLoggedExpiry = false; // Paper ++ private boolean hasLoggedExpiry = false; // Paper - Prevent causing expired keys from impacting new joins private SignedMessageChain.Decoder signedMessageDecoder; private final LastSeenMessagesValidator lastSeenMessages = new LastSeenMessagesValidator(20); private final MessageSignatureCache messageSignatureCache = MessageSignatureCache.createDefault(); @@ -39,12 +39,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause } -+ // Paper start ++ // Paper start - Prevent causing expired keys from impacting new joins + if (!hasLoggedExpiry && this.chatSession != null && this.chatSession.profilePublicKey().data().hasExpired()) { + LOGGER.info("Player profile key for {} has expired!", this.player.getName().getString()); + hasLoggedExpiry = true; + } -+ // Paper end ++ // Paper end - Prevent causing expired keys from impacting new joins + } @@ -53,7 +53,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private void resetPlayerChatState(RemoteChatSession session) { this.chatSession = session; -+ this.hasLoggedExpiry = false; // Paper ++ this.hasLoggedExpiry = false; // Paper - Prevent causing expired keys from impacting new joins this.signedMessageDecoder = session.createMessageDecoder(this.player.getUUID()); this.chatMessageChain.append(() -> { this.player.setChatSession(session); diff --git a/patches/server/Properly-Cancel-Usable-Items.patch b/patches/server/Properly-cancel-usable-items.patch similarity index 89% rename from patches/server/Properly-Cancel-Usable-Items.patch rename to patches/server/Properly-cancel-usable-items.patch index 3d42cdddcd..0c30d7ac0c 100644 --- a/patches/server/Properly-Cancel-Usable-Items.patch +++ b/patches/server/Properly-cancel-usable-items.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> Date: Tue, 23 May 2023 22:33:36 -0400 -Subject: [PATCH] Properly Cancel Usable Items +Subject: [PATCH] Properly cancel usable items This fixes the bug causing cancelling PlayerInteractEvent to cause items to continue to be used despite being cancelled on the server. @@ -17,7 +17,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } // Paper end - extend Player Interact cancellation player.getBukkitEntity().updateInventory(); // SPIGOT-2867 -+ this.player.resyncUsingItem(this.player); // Paper - Resend player's using item status ++ this.player.resyncUsingItem(this.player); // Paper - Properly cancel usable items enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS; } else if (this.gameModeForPlayer == GameType.SPECTATOR) { MenuProvider itileinventory = iblockdata.getMenuProvider(world, blockposition); @@ -25,11 +25,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return enuminteractionresult1; } -+ // Paper start - Cancel only if cancelled + if the interact result is different from default response ++ // Paper start - Properly cancel usable items; Cancel only if cancelled + if the interact result is different from default response + else if (this.interactResult && this.interactResult != cancelledItem) { + this.player.resyncUsingItem(this.player); + } -+ // Paper end ++ // Paper end - Properly cancel usable items } return enuminteractionresult; // CraftBukkit end @@ -41,7 +41,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } if (cancelled) { -+ this.player.resyncUsingItem(this.player); // Paper - Resend player's using item status ++ this.player.resyncUsingItem(this.player); // Paper - Properly cancel usable items this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524 return; } @@ -53,11 +53,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; } -+ // Paper start ++ // Paper start - Properly cancel usable items + public void resyncUsingItem(ServerPlayer serverPlayer) { + this.getEntityData().resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer); + } -+ // Paper end ++ // Paper end - Properly cancel usable items private void updatingUsingItem() { if (this.isUsingItem()) { if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) { diff --git a/patches/server/Refresh-ProjectileSource-for-projectiles.patch b/patches/server/Refresh-ProjectileSource-for-projectiles.patch index 8ece52b88e..cbd47de483 100644 --- a/patches/server/Refresh-ProjectileSource-for-projectiles.patch +++ b/patches/server/Refresh-ProjectileSource-for-projectiles.patch @@ -21,7 +21,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean inWorld = false; public boolean generation; public int maxAirTicks = this.getDefaultMaxAirSupply(); // CraftBukkit - SPIGOT-6907: re-implement LivingEntity#setMaximumAir() -+ @Nullable // Paper ++ @Nullable // Paper - Refresh ProjectileSource for projectiles public org.bukkit.projectiles.ProjectileSource projectileSource; // For projectiles only public boolean lastDamageCancelled; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled public boolean persistentInvisibility = false; @@ -35,16 +35,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - this.projectileSource = (entity != null && entity.getBukkitEntity() instanceof ProjectileSource) ? (ProjectileSource) entity.getBukkitEntity() : null; // CraftBukkit - -+ // Paper start - Fix null owners not being handled ++ // Paper start - Refresh ProjectileSource for projectiles + else { + this.ownerUUID = null; + this.cachedOwner = null; + this.projectileSource = null; + } -+ // Paper end ++ // Paper end - Refresh ProjectileSource for projectiles + this.refreshProjectileSource(false); // Paper + } -+ // Paper start ++ // Paper start - Refresh ProjectileSource for projectiles + public void refreshProjectileSource(boolean fillCache) { + if (fillCache) { + this.getOwner(); @@ -53,13 +53,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.projectileSource = projSource; + } } -+ // Paper end ++ // Paper end - Refresh ProjectileSource for projectiles @Nullable @Override public Entity getOwner() { if (this.cachedOwner != null && !this.cachedOwner.isRemoved()) { -+ this.refreshProjectileSource(false); // Paper ++ this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles return this.cachedOwner; } else { if (this.ownerUUID != null) { @@ -67,7 +67,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 ServerLevel worldserver = (ServerLevel) world; this.cachedOwner = worldserver.getEntity(this.ownerUUID); -+ this.refreshProjectileSource(false); // Paper ++ this.refreshProjectileSource(false); // Paper - Refresh ProjectileSource for projectiles return this.cachedOwner; } } @@ -79,7 +79,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @Override public final org.bukkit.projectiles.ProjectileSource getShooter() { -+ this.getHandle().refreshProjectileSource(true); // Paper ++ this.getHandle().refreshProjectileSource(true); // Paper - Refresh ProjectileSource for projectiles return this.getHandle().projectileSource; } diff --git a/patches/server/Temp-Pre-init-PlayerChunkLoaderData-in-order-to-prep.patch b/patches/server/Temp-Pre-init-PlayerChunkLoaderData-in-order-to-prep.patch index 05c2133858..ef0a191f84 100644 --- a/patches/server/Temp-Pre-init-PlayerChunkLoaderData-in-order-to-prep.patch +++ b/patches/server/Temp-Pre-init-PlayerChunkLoaderData-in-order-to-prep.patch @@ -13,7 +13,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 tryPreloadClass(net.minecraft.world.level.lighting.LayerLightEventListener.DummyLightLayerEventListener.class.getName()); tryPreloadClass(net.minecraft.world.level.lighting.LayerLightEventListener.class.getName()); tryPreloadClass(net.minecraft.util.ExceptionCollector.class.getName()); -+ tryPreloadClass(io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.PlayerChunkLoaderData.class.getName()); ++ tryPreloadClass(io.papermc.paper.chunk.system.RegionizedPlayerChunkLoader.PlayerChunkLoaderData.class.getName()); // Paper - Prepopulate BFS lookup for potatos // Paper end } } diff --git a/patches/server/Treat-sequence-violations-like-they-should-be.patch b/patches/server/Treat-sequence-violations-like-they-should-be.patch index 439989280e..499bd3b547 100644 --- a/patches/server/Treat-sequence-violations-like-they-should-be.patch +++ b/patches/server/Treat-sequence-violations-like-they-should-be.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void ackBlockChangesUpTo(int sequence) { if (sequence < 0) { -+ this.disconnect("Expected packet sequence nr >= 0", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper ++ this.disconnect("Expected packet sequence nr >= 0", org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - Treat sequence violations like they should be throw new IllegalArgumentException("Expected packet sequence nr >= 0"); } else { this.ackBlockChangesUpTo = Math.max(sequence, this.ackBlockChangesUpTo); diff --git a/patches/server/Use-array-for-gamerule-storage.patch b/patches/server/Use-array-for-gamerule-storage.patch index 34436c32da..c14b604519 100644 --- a/patches/server/Use-array-for-gamerule-storage.patch +++ b/patches/server/Use-array-for-gamerule-storage.patch @@ -12,7 +12,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static final GameRules.Key RULE_DO_VINES_SPREAD = GameRules.register("doVinesSpread", GameRules.Category.UPDATES, GameRules.BooleanValue.create(true)); public static final GameRules.Key RULE_ENDER_PEARLS_VANISH_ON_DEATH = GameRules.register("enderPearlsVanishOnDeath", GameRules.Category.PLAYER, GameRules.BooleanValue.create(true)); private final Map, GameRules.Value> rules; -+ private final GameRules.Value[] gameruleArray; // Paper ++ private final GameRules.Value[] gameruleArray; // Paper - Perf: Use array for gamerule storage private static > GameRules.Key register(String name, GameRules.Category category, GameRules.Type type) { GameRules.Key gamerules_gamerulekey = new GameRules.Key<>(name, category); @@ -21,18 +21,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public GameRules() { - this.rules = (Map) GameRules.GAME_RULE_TYPES.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry) -> { -+ // Paper start - use this to ensure gameruleArray is initialized ++ // Paper start - Perf: Use array for gamerule storage + this((Map) GameRules.GAME_RULE_TYPES.entrySet().stream().collect(ImmutableMap.toImmutableMap(Entry::getKey, (entry) -> { return ((GameRules.Type) entry.getValue()).createRule(); - })); + }))); -+ // Paper end ++ // Paper end - Perf: Use array for gamerule storage } private GameRules(Map, GameRules.Value> rules) { this.rules = rules; + -+ // Paper start ++ // Paper start - Perf: Use array for gamerule storage + int arraySize = rules.keySet().stream().mapToInt(key -> key.gameRuleIndex).max().orElse(-1) + 1; + GameRules.Value[] values = new GameRules.Value[arraySize]; + @@ -41,12 +41,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + this.gameruleArray = values; -+ // Paper end ++ // Paper end - Perf: Use array for gamerule storage } public > T getRule(GameRules.Key key) { - return (T) this.rules.get(key); // CraftBukkit - decompile error -+ return key == null ? null : (T) this.gameruleArray[key.gameRuleIndex]; // Paper ++ return key == null ? null : (T) this.gameruleArray[key.gameRuleIndex]; // Paper - Perf: Use array for gamerule storage } public CompoundTag createTag() { @@ -54,10 +54,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public static final class Key> { -+ // Paper start ++ // Paper start - Perf: Use array for gamerule storage + private static int lastGameRuleIndex = 0; + public final int gameRuleIndex = lastGameRuleIndex++; -+ // Paper end ++ // Paper end - Perf: Use array for gamerule storage final String id; private final GameRules.Category category;