From 9dd3505d63e7d4dcf03d124baca3c385c3dd1bd8 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sat, 6 Jul 2024 00:25:18 +0200 Subject: [PATCH 1/5] Updated Upstream (Bukkit/CraftBukkit/Spigot) Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: e86f4dc4 PR-1041: Improve getPlayer(String) docs to clarify it matches the name 9738f005 Fix spawner API documentation 69ebd9fd PR-1034: Add TrialSpawnerSpawnEvent 23cffd9c PR-973: Improve spawner API and add API for Trial Spawners 8bf19163 PR-1038: Clarify HumanEntity#openInventory(InventoryView) JavaDoc 1ff76351 SPIGOT-7732, SPIGOT-7786: Add freezing damage modifier 02161cb4 PR-1034: Add CreatureSpawnEvent.SpawnReason#TRIAL_SPAWNER f9cb6f34 SPIGOT-7777: All entity potion effects are removed on death 25d548eb PR-1031: Expose Creeper igniter ccbf0915 SPIGOT-7770: Reserve spaces in shaped recipes for blank ingredients 17f7097c Clarify ambiguity around what is API 71714f0c Remove note from InventoryView JavaDoc aaf49731 PR-1030: Deprecate more unused methods in UnsafeValues 3a9dc689 SPIGOT-7771: Material.getDefaultAttributes always returns an empty map CraftBukkit Changes: c3ceeb6f7 SPIGOT-7814: Call PlayerShearEntityEvent for Bogged 97b1e4f58 Fix wolf armor not dropping from use of shears fd2ef563a SPIGOT-7812: Revert "SPIGOT-7809: Restore shield/banner conversion for base colours" f672c351b SPIGOT-7811: Enchantments are applied on sweeping attack even if damage event is cancelled cfe29350b SPIGOT-7808: Fix implementation of Enchantment#getName() for bad name return 19335f69e SPIGOT-7809: Restore shield/banner conversion for base colours ae4f5a0be SPIGOT-7805: Fix jukebox deserialization 62e3b73a4 SPIGOT-7804: Fix written book serialization aac911d26 SPIGOT-7800, SPIGOT-7801: Keep vanilla behaviour for items dropped on player death 13ece474f PR-1429: Implement TrialSpawnerSpawnEvent bf13e9113 PR-1354: Improve spawner API and add API for Trial Spawners 515fe49e1 Increase outdated build delay 9cd5a19a0 SPIGOT-7794: Cancelling InventoryItemMoveEvent destroys items ce40c7b14 SPIGOT-7796: Kickplayer newlines not working 5167256ff SPIGOT-7795: Fix damage/stats ignore the invulnerable damage time f993563ee Improve cross-world teleportation handling ab29122cf PR-1433: HumanEntity#openInventory(InventoryView) should only support views belonging to the player 764a541c5 SPIGOT-7732: Issue with the "hurt()" method of EntityLiving and invulnerable time 820084b5f SPIGOT-7791: Skull BlockState with null profile causes NullPointerException 5e46f1c82 SPIGOT-7785: Teleporting a player at the right moment can mess up vanilla teleportation cbd95a6b3 SPIGOT-7772: Include hidden / non-sampled players in player count 3153debc5 SPIGOT-7790: Server crashes after bee nest is forced to update e77bb26bb SPIGOT-7788: The healing power of friendship advancement is never granted ee3d7258a SPIGOT-7789: Fix NPE in CraftMetaFirework applyToItem 2889b3a11 PR-1429: Add CreatureSpawnEvent.SpawnReason#TRIAL_SPAWNER cdd05bc7f SPIGOT-7777: Speed attribute stays after death; missing EntityPotionEffectEvent call d0e6af2d4 PR-1428: Expose Creeper igniter d01c70e93 PR-1425: Fix bytecode transformation taking care of class-to-interface compatibility. b2b08f68c SPIGOT-7770: Fix certain shaped recipes not registering 3f8e4161f PR-1426: Deprecate more unused methods in UnsafeValues 2c9dd879e SPIGOT-7771: Material.getDefaultAttributes always returns an empty map Spigot Changes: 491f3675 Rebuild patches 0a642bd7 Rebuild patches 8897571b Rebuild patches cb8cf80c Fix newlines in custom restart message 1aabe506 Rebuild patches --- patches/api/0006-Adventure.patch | 48 +- patches/api/0009-Paper-Plugins.patch | 4 +- patches/api/0011-Timings-v2.patch | 12 +- patches/api/0014-Add-getTPS-method.patch | 8 +- ...0015-Expose-server-build-information.patch | 8 +- .../api/0019-Expose-server-CommandMap.patch | 8 +- ...eload-permissions.yml-and-require-co.patch | 8 +- ...2-Allow-Reloading-of-Command-Aliases.patch | 8 +- ...n-option-to-prevent-player-names-fro.patch | 8 +- patches/api/0053-Fix-upstream-javadocs.patch | 20 +- .../api/0057-Basic-PlayerProfile-API.patch | 8 +- .../0059-Shoulder-Entities-Release-API.patch | 4 +- .../0089-Player.setPlayerProfile-API.patch | 16 +- patches/api/0090-getPlayerUniqueId-API.patch | 8 +- ...2-Add-openSign-method-to-HumanEntity.patch | 4 +- .../0114-LivingEntity-Active-Item-API.patch | 4 +- .../0117-InventoryCloseEvent-Reason-API.patch | 4 +- patches/api/0135-Add-More-Creeper-API.patch | 8 +- ...ault-permission-message-configurable.patch | 8 +- ...-ItemStack-Recipe-API-helper-methods.patch | 4 +- .../0166-Fix-Spigot-annotation-mistakes.patch | 38 +- .../0170-Mob-Spawner-API-Enhancements.patch | 14 +- ...174-Expose-the-internal-current-tick.patch | 8 +- patches/api/0180-Add-tick-times-API.patch | 8 +- ...181-Expose-MinecraftServer-isRunning.patch | 8 +- ...Add-Raw-Byte-ItemStack-Serialization.patch | 4 +- patches/api/0187-Add-Mob-Goal-API.patch | 8 +- patches/api/0190-Potential-bed-API.patch | 4 +- ...al-open-container-api-to-HumanEntity.patch | 4 +- ...y-Counter-to-allow-plugins-to-use-va.patch | 4 +- ...-Add-getOfflinePlayerIfCached-String.patch | 8 +- ...0-Expose-LivingEntity-hurt-direction.patch | 4 +- ...gistryAccess-for-managing-registries.patch | 8 +- patches/api/0253-Expand-world-key-API.patch | 12 +- .../api/0255-Expose-protocol-version.patch | 4 +- ...-add-isDeeplySleeping-to-HumanEntity.patch | 4 +- patches/api/0270-Add-basic-Datapack-API.patch | 8 +- .../api/0272-ItemStack-repair-check-API.patch | 4 +- .../0304-Get-entity-default-attributes.patch | 4 +- ...12-Add-Raw-Byte-Entity-Serialization.patch | 4 +- ...-command-sender-which-forwards-feedb.patch | 8 +- patches/api/0336-Custom-Potion-Mixes.patch | 8 +- ...Add-method-isTickingWorlds-to-Bukkit.patch | 12 +- patches/api/0352-Add-Player-getFishHook.patch | 4 +- ...0358-Add-NamespacedKey-biome-methods.patch | 4 +- ...Folia-scheduler-and-owned-region-API.patch | 8 +- ...-API-for-updating-recipes-on-clients.patch | 16 +- ...x-custom-statistic-criteria-creation.patch | 4 +- ...place-methods-with-old-StructureType.patch | 14 +- ...0431-Experimental-annotations-change.patch | 7 +- ...Add-api-for-spawn-egg-texture-colors.patch | 4 +- .../api/0444-Add-Lifecycle-Event-system.patch | 4 +- patches/api/0445-ItemStack-Tooltip-API.patch | 4 +- patches/api/0449-improve-BanList-types.patch | 8 +- .../api/0470-Fix-issues-with-recipe-API.patch | 6 +- .../api/0476-Registry-Modification-API.patch | 4 +- ...78-Proxy-ItemStack-to-CraftItemStack.patch | 4 +- .../server/0003-Build-system-changes.patch | 4 +- patches/server/0008-CB-fixes.patch | 6 +- patches/server/0009-MC-Utils.patch | 14 +- patches/server/0010-Adventure.patch | 57 +- patches/server/0019-Paper-Plugins.patch | 4 +- .../0021-Hook-into-CB-plugin-rewrites.patch | 14 +- ...ion-calls-in-plugins-using-internals.patch | 8 +- patches/server/0023-Timings-v2.patch | 28 +- ...0034-Expose-server-build-information.patch | 8 +- .../0035-Player-affects-spawning-API.patch | 8 +- ...036-Only-refresh-abilities-if-needed.patch | 4 +- .../0049-Use-null-Locale-by-default.patch | 6 +- ...oreboards-for-non-players-by-default.patch | 4 +- .../0067-Complete-resource-pack-API.patch | 4 +- ...071-Handle-Item-Meta-Inconsistencies.patch | 4 +- ...4-Custom-replacement-for-eaten-items.patch | 8 +- ...th-absorb-values-and-repair-bad-data.patch | 12 +- ...0084-Add-PlayerUseUnknownEntityEvent.patch | 4 +- ...ityRegainHealthEvent-isFastRegen-API.patch | 4 +- patches/server/0109-Add-EntityZapEvent.patch | 4 +- ...3-Add-source-to-PlayerExpChangeEvent.patch | 4 +- .../0114-Add-ProjectileCollideEvent.patch | 6 +- ...21-Properly-fix-item-duplication-bug.patch | 4 +- ...PI-for-Reason-Source-Triggering-play.patch | 10 +- .../server/0127-Cap-Entity-Collisions.patch | 4 +- ...le-async-calls-to-restart-the-server.patch | 6 +- ...ke-parrots-stay-on-shoulders-despite.patch | 4 +- .../0139-Shoulder-Entities-Release-API.patch | 8 +- .../0147-Fix-this-stupid-bullshit.patch | 4 +- ...dEffects-only-to-players-who-can-see.patch | 12 +- .../0157-Add-PlayerArmorChangeEvent.patch | 4 +- ...4-Ability-to-apply-mending-to-XP-API.patch | 4 +- .../server/0173-Toggleable-player-crits.patch | 4 +- .../0177-Player.setPlayerProfile-API.patch | 16 +- ...82-Flag-to-disable-the-channel-limit.patch | 4 +- ...3-Add-openSign-method-to-HumanEntity.patch | 4 +- ...urable-sprint-interruption-on-attack.patch | 4 +- .../server/0193-WitchReadyPotionEvent.patch | 4 +- ...e-shield-blocking-delay-configurable.patch | 4 +- .../server/0202-PlayerReadyArrowEvent.patch | 4 +- .../0203-Add-entity-knockback-events.patch | 30 +- .../0209-InventoryCloseEvent-Reason-API.patch | 22 +- ...8-Vanished-players-don-t-have-rights.patch | 4 +- .../server/0239-Add-More-Creeper-API.patch | 6 +- ...-ray-tracing-methods-to-LivingEntity.patch | 4 +- ...e-attack-cooldown-methods-for-Player.patch | 4 +- .../server/0244-Improve-death-events.patch | 25 +- ...254-Add-LivingEntity-getTargetEntity.patch | 4 +- ...61-Reset-players-airTicks-on-respawn.patch | 4 +- ...entity-dismount-during-teleportation.patch | 12 +- ...-Replace-OfflinePlayer-getLastPlayed.patch | 10 +- .../0289-Mob-Spawner-API-Enhancements.patch | 143 +- ...revent-consuming-the-wrong-itemstack.patch | 8 +- patches/server/0319-Entity-Jump-API.patch | 4 +- ...322-add-hand-to-BlockMultiPlaceEvent.patch | 4 +- ...Add-Raw-Byte-ItemStack-Serialization.patch | 4 +- ...d-Player-s-shouldn-t-be-able-to-move.patch | 4 +- ...vent-opening-inventories-when-frozen.patch | 6 +- ...-entity-collision-code-if-not-needed.patch | 4 +- ...PlayerAttackEntityCooldownResetEvent.patch | 11 +- ...item-duplication-and-teleport-issues.patch | 12 +- ...ceOrb-merging-stacking-API-and-fixes.patch | 4 +- ...ve-fix-EntityTargetLivingEntityEvent.patch | 11 +- .../server/0385-Add-PrepareResultEvent.patch | 8 +- ...k-for-portal-on-world-gen-entity-add.patch | 4 +- patches/server/0395-Brand-support.patch | 6 +- patches/server/0402-Add-BellRingEvent.patch | 4 +- ...-Add-methods-to-get-translation-keys.patch | 10 +- ...al-open-container-api-to-HumanEntity.patch | 4 +- ...y-Counter-to-allow-plugins-to-use-va.patch | 4 +- ...ix-client-lag-on-advancement-loading.patch | 4 +- ...r-spawnParticle-x-y-z-precision-loss.patch | 4 +- ...-should-not-bypass-cramming-gamerule.patch | 6 +- ...9-Expose-LivingEntity-hurt-direction.patch | 6 +- ...-OBSTRUCTED-reason-to-BedEnterResult.patch | 4 +- .../0467-Add-BlockFailedDispenseEvent.patch | 4 +- .../0482-Add-BlockPreDispenseEvent.patch | 4 +- .../0486-Expand-EntityUnleashEvent.patch | 4 +- patches/server/0489-Add-EntityMoveEvent.patch | 4 +- ...w-adding-items-to-BlockDropItemEvent.patch | 4 +- .../server/0505-Expand-world-key-API.patch | 4 +- .../server/0510-Expose-protocol-version.patch | 4 +- ...ItemConsumeEvent-cancelling-properly.patch | 4 +- .../0520-Add-PlayerDeepSleepEvent.patch | 4 +- ...536-Expand-PlayerGameModeChangeEvent.patch | 8 +- .../0537-ItemStack-repair-check-API.patch | 4 +- .../server/0538-More-Enchantment-API.patch | 6 +- ...4-Improve-item-default-attribute-API.patch | 37 +- .../0548-Add-PlayerKickEvent-causes.patch | 12 +- .../server/0557-Line-Of-Sight-Changes.patch | 4 +- .../0559-Fix-potions-splash-events.patch | 4 +- ...PlayerDropItemEvent-using-wrong-item.patch | 12 +- .../0570-Add-missing-forceDrop-toggles.patch | 14 - .../server/0575-Add-PlayerSetSpawnEvent.patch | 6 +- ...ers-respect-inventory-max-stack-size.patch | 4 +- .../0589-Get-entity-default-attributes.patch | 4 +- .../0591-Add-more-advancement-API.patch | 4 +- ...0592-Add-ItemFactory-getSpawnEgg-API.patch | 4 +- .../server/0593-Add-critical-damage-API.patch | 14 +- ...98-Add-Raw-Byte-Entity-Serialization.patch | 4 +- ...-logic-for-inventories-on-chunk-unlo.patch | 6 +- ...0602-Improve-and-expand-AsyncCatcher.patch | 4 +- ...sive-velocity-through-repeated-crits.patch | 4 +- .../server/0660-Freeze-Tick-Lock-API.patch | 4 +- patches/server/0679-More-Projectile-API.patch | 6 +- ...lock-data-for-EntityChangeBlockEvent.patch | 4 +- ...ables-running-when-mob-loot-gamerule.patch | 8 +- ...eEvent-and-CollarColorable-interface.patch | 4 +- .../0703-Add-PlayerStopUsingItemEvent.patch | 4 +- patches/server/0717-Nameable-Banner-API.patch | 4 +- patches/server/0726-More-Teleport-API.patch | 4 +- ...0737-Add-NamespacedKey-biome-methods.patch | 4 +- ...ook-changes-from-crashing-the-server.patch | 4 +- .../0741-Missing-eating-regain-reason.patch | 4 +- ...-of-WorldCreator-keepSpawnLoaded-ret.patch | 4 +- ...-interactions-with-items-on-cooldown.patch | 6 +- .../0757-Elder-Guardian-appearance-API.patch | 4 +- .../0762-Add-EntityToggleSitEvent.patch | 8 +- .../0768-Add-PrePlayerAttackEntityEvent.patch | 4 +- .../0770-Add-Player-Warden-Warning-API.patch | 4 +- ...global-player-list-where-appropriate.patch | 4 +- patches/server/0776-Friction-API.patch | 6 +- patches/server/0793-Flying-Fall-Damage.patch | 10 +- ...nk-items-during-EntityResurrectEvent.patch | 4 +- .../0803-Add-EntityFertilizeEggEvent.patch | 4 +- ...ity-drop-not-updating-the-client-inv.patch | 4 +- ...vancement-triggers-for-entity-damage.patch | 6 +- .../0823-Expand-PlayerItemMendEvent.patch | 8 +- ...0838-Call-missing-BlockDispenseEvent.patch | 4 +- patches/server/0843-Fix-BanList-API.patch | 6 +- ...enceOrb-should-call-EntitySpawnEvent.patch | 4 +- ...x-custom-statistic-criteria-creation.patch | 4 +- .../0870-Add-Listing-API-for-Player.patch | 6 +- ...72-Add-BlockFace-to-BlockDamageEvent.patch | 4 +- ...-titleOverride-to-InventoryOpenEvent.patch | 14 +- ...899-Fix-UnsafeValues-loadAdvancement.patch | 4 +- .../0900-Add-player-idle-duration-API.patch | 4 +- ...tem-packets-with-collector-as-source.patch | 4 +- ...several-issues-with-EntityBreedEvent.patch | 16 +- ...n-t-fire-sync-events-during-worldgen.patch | 8 +- ...estore-vanilla-entity-drops-behavior.patch | 33 +- ...-on-null-loc-for-EntityTeleportEvent.patch | 4 +- .../0923-Add-experience-points-API.patch | 8 +- .../0924-Add-drops-to-shear-events.patch | 68 +- .../0925-Add-PlayerShieldDisableEvent.patch | 6 +- ...date-ResourceLocation-in-NBT-reading.patch | 4 +- .../0928-Fixup-NamespacedKey-handling.patch | 4 +- ...Add-api-for-spawn-egg-texture-colors.patch | 4 +- .../0934-Add-Lifecycle-Event-system.patch | 4 +- .../server/0935-ItemStack-Tooltip-API.patch | 4 +- ...962-Fix-shield-disable-inconsistency.patch | 4 +- ...met-damage-reduction-inconsistencies.patch | 10 +- ...a-handling-of-LivingEntity-actuallyH.patch | 18 +- ...ve-checking-handled-tags-in-itemmeta.patch | 3010 ++++++++++++++++- .../server/0970-General-ItemMeta-fixes.patch | 535 ++- ...977-Fix-equipment-slot-and-group-API.patch | 30 +- ...oversized-item-data-in-equipment-and.patch | 4 +- ...amage-tick-when-blocking-with-shield.patch | 4 +- ...Chunk-System-Starlight-from-Moonrise.patch | 10 +- .../0992-Rewrite-dataconverter-system.patch | 6 +- ...item-frames-performance-and-bug-fixe.patch | 4 +- ...cing-for-EntityLiving-hasLineOfSight.patch | 4 +- patches/server/1009-Optimize-Hoppers.patch | 30 +- .../1018-API-for-checking-sent-chunks.patch | 4 +- ...9-Improve-boat-collision-performance.patch | 8 +- .../1023-Properly-resend-entities.patch | 6 +- .../1025-Registry-Modification-API.patch | 4 +- ...28-Proxy-ItemStack-to-CraftItemStack.patch | 6 +- ...aft-commands-in-function-parsing-an.patch} | 0 ...31-optimize-dirt-and-snow-spreading.patch} | 0 ... 1032-Fix-NPE-for-Jukebox-setRecord.patch} | 0 ...033-Fix-CraftWorld-isChunkGenerated.patch} | 0 ...debug-for-chunk-system-unload-crash.patch} | 0 work/Bukkit | 2 +- work/CraftBukkit | 2 +- work/Spigot | 2 +- 233 files changed, 4173 insertions(+), 1266 deletions(-) rename patches/server/{1029-Prioritize-Minecraft-commands-in-function-parsing.patch => 1030-Prioritize-Minecraft-commands-in-function-parsing-an.patch} (100%) rename patches/server/{1030-optimize-dirt-and-snow-spreading.patch => 1031-optimize-dirt-and-snow-spreading.patch} (100%) rename patches/server/{1031-Fix-NPE-for-Jukebox-setRecord.patch => 1032-Fix-NPE-for-Jukebox-setRecord.patch} (100%) rename patches/server/{1032-Fix-CraftWorld-isChunkGenerated.patch => 1033-Fix-CraftWorld-isChunkGenerated.patch} (100%) rename patches/server/{1033-Add-debug-for-chunk-system-unload-crash.patch => 1034-Add-debug-for-chunk-system-unload-crash.patch} (100%) diff --git a/patches/api/0006-Adventure.patch b/patches/api/0006-Adventure.patch index 95c380c78e0d..c67a70e9a96e 100644 --- a/patches/api/0006-Adventure.patch +++ b/patches/api/0006-Adventure.patch @@ -766,7 +766,7 @@ index 0000000000000000000000000000000000000000..1a11cfde07db55194cd26757863a268b + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf146cd1830 100644 +index 67b6e7e6740cd0f98e2de8087ad87fdf9cdf83d1..fe6c43405e3f11272c1ff015f1dcd47129a68d41 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -423,7 +423,9 @@ public final class Bukkit { @@ -779,7 +779,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 public static int broadcastMessage(@NotNull String message) { return server.broadcastMessage(message); } -@@ -1224,6 +1226,19 @@ public final class Bukkit { +@@ -1227,6 +1229,19 @@ public final class Bukkit { server.shutdown(); } @@ -799,7 +799,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 /** * Broadcasts the specified message to every user with the given * permission name. -@@ -1233,6 +1248,21 @@ public final class Bukkit { +@@ -1236,6 +1251,21 @@ public final class Bukkit { * permissibles} must have to receive the broadcast * @return number of message recipients */ @@ -821,7 +821,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 public static int broadcast(@NotNull String message, @NotNull String permission) { return server.broadcast(message, permission); } -@@ -1494,6 +1524,7 @@ public final class Bukkit { +@@ -1497,6 +1527,7 @@ public final class Bukkit { return server.createInventory(owner, type); } @@ -829,7 +829,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 /** * Creates an empty inventory with the specified type and title. If the type * is {@link InventoryType#CHEST}, the new inventory has a size of 27; -@@ -1519,6 +1550,38 @@ public final class Bukkit { +@@ -1522,6 +1553,38 @@ public final class Bukkit { * @see InventoryType#isCreatable() */ @NotNull @@ -868,7 +868,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 public static Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title) { return server.createInventory(owner, type, title); } -@@ -1537,6 +1600,7 @@ public final class Bukkit { +@@ -1540,6 +1603,7 @@ public final class Bukkit { return server.createInventory(owner, size); } @@ -876,7 +876,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 /** * Creates an empty inventory of type {@link InventoryType#CHEST} with the * specified size and title. -@@ -1549,10 +1613,30 @@ public final class Bukkit { +@@ -1552,10 +1616,30 @@ public final class Bukkit { * @throws IllegalArgumentException if the size is not a multiple of 9 */ @NotNull @@ -907,7 +907,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 /** * Creates an empty merchant. * -@@ -1560,7 +1644,20 @@ public final class Bukkit { +@@ -1563,7 +1647,20 @@ public final class Bukkit { * when the merchant inventory is viewed * @return a new merchant */ @@ -928,7 +928,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 public static Merchant createMerchant(@Nullable String title) { return server.createMerchant(title); } -@@ -1677,12 +1774,43 @@ public final class Bukkit { +@@ -1680,12 +1777,43 @@ public final class Bukkit { return server.isPrimaryThread(); } @@ -972,7 +972,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 public static String getMotd() { return server.getMotd(); } -@@ -1691,7 +1819,9 @@ public final class Bukkit { +@@ -1694,7 +1822,9 @@ public final class Bukkit { * Set the message that is displayed on the server list. * * @param motd The message to be displayed @@ -982,7 +982,7 @@ index 4a6b495a4c21b631380b6decac8207ab026a1e21..87948f6c3b55bbf115561292544e8cf1 public static void setMotd(@NotNull String motd) { server.setMotd(motd); } -@@ -1711,8 +1841,10 @@ public final class Bukkit { +@@ -1714,8 +1844,10 @@ public final class Bukkit { * Gets the default message that is displayed when the server is stopped. * * @return the shutdown message @@ -1183,7 +1183,7 @@ index 9562fcd522b2e2b24ec57fbf18ddeebba3e50abf..9b61129c3ef83d0bfceba54aba2effa1 + // Paper end } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3a6b1b443 100644 +index 19d2b0abfef1cff5d7c5ce661416c6b53a307dc2..fa6ad07214d5e38866bf6bee9139c6c938e9f51a 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -66,13 +66,13 @@ import org.jetbrains.annotations.Nullable; @@ -1221,7 +1221,7 @@ index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3 public int broadcastMessage(@NotNull String message); /** -@@ -1050,8 +1052,33 @@ public interface Server extends PluginMessageRecipient { +@@ -1053,8 +1055,33 @@ public interface Server extends PluginMessageRecipient { * @param permission the required permission {@link Permissible * permissibles} must have to receive the broadcast * @return number of message recipients @@ -1255,7 +1255,7 @@ index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3 /** * Gets the player by the given name, regardless if they are offline or -@@ -1268,6 +1295,35 @@ public interface Server extends PluginMessageRecipient { +@@ -1271,6 +1298,35 @@ public interface Server extends PluginMessageRecipient { @NotNull Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type); @@ -1291,7 +1291,7 @@ index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3 /** * Creates an empty inventory with the specified type and title. If the type * is {@link InventoryType#CHEST}, the new inventory has a size of 27; -@@ -1289,9 +1345,11 @@ public interface Server extends PluginMessageRecipient { +@@ -1292,9 +1348,11 @@ public interface Server extends PluginMessageRecipient { * @return The new inventory. * @throws IllegalArgumentException if the {@link InventoryType} cannot be * viewed. @@ -1303,7 +1303,7 @@ index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3 @NotNull Inventory createInventory(@Nullable InventoryHolder owner, @NotNull InventoryType type, @NotNull String title); -@@ -1307,6 +1365,22 @@ public interface Server extends PluginMessageRecipient { +@@ -1310,6 +1368,22 @@ public interface Server extends PluginMessageRecipient { @NotNull Inventory createInventory(@Nullable InventoryHolder owner, int size) throws IllegalArgumentException; @@ -1326,7 +1326,7 @@ index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3 /** * Creates an empty inventory of type {@link InventoryType#CHEST} with the * specified size and title. -@@ -1317,18 +1391,32 @@ public interface Server extends PluginMessageRecipient { +@@ -1320,18 +1394,32 @@ public interface Server extends PluginMessageRecipient { * viewed * @return a new inventory * @throws IllegalArgumentException if the size is not a multiple of 9 @@ -1359,7 +1359,7 @@ index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3 Merchant createMerchant(@Nullable String title); /** -@@ -1424,19 +1512,46 @@ public interface Server extends PluginMessageRecipient { +@@ -1427,19 +1515,46 @@ public interface Server extends PluginMessageRecipient { */ boolean isPrimaryThread(); @@ -1406,7 +1406,7 @@ index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3 void setMotd(@NotNull String motd); /** -@@ -1452,8 +1567,10 @@ public interface Server extends PluginMessageRecipient { +@@ -1455,8 +1570,10 @@ public interface Server extends PluginMessageRecipient { * Gets the default message that is displayed when the server is stopped. * * @return the shutdown message @@ -1417,7 +1417,7 @@ index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3 String getShutdownMessage(); /** -@@ -1844,7 +1961,9 @@ public interface Server extends PluginMessageRecipient { +@@ -1847,7 +1964,9 @@ public interface Server extends PluginMessageRecipient { * Sends the component to the player * * @param component the components to send @@ -1427,7 +1427,7 @@ index 7ffbf7e72275b3111ecb87824fa68f44d4300799..ddbaa7fb174e05533023a2523d67c3d3 public void broadcast(@NotNull net.md_5.bungee.api.chat.BaseComponent component) { throw new UnsupportedOperationException("Not supported yet."); } -@@ -1853,7 +1972,9 @@ public interface Server extends PluginMessageRecipient { +@@ -1856,7 +1975,9 @@ public interface Server extends PluginMessageRecipient { * Sends an array of components as a single message to the player * * @param components the components to send @@ -1555,7 +1555,7 @@ index ac5e263d737973af077e3406a84a84baca4370db..2d91924b7f5ef16a91d40cdc1bfc3d68 + // Paper end } diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index ce9bb54a6ef8a7d31804ec63aa1f6cbbd6ae2d54..baf49da3dd46039da2f24a4af8b1b8617bb25501 100644 +index 0bb3637d73132f1882af38ca7ad6864a44812edc..9ba1a4e838538ecd55f4f8e50ffb0c5f1f474382 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java @@ -30,6 +30,15 @@ import org.jetbrains.annotations.Nullable; @@ -4327,10 +4327,10 @@ index 5adbe0514129abf3cfbc4b29a213f522359fe2e1..72ebc29db42d08d1d0361dba462fc8a5 /** diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java -index 6a8a9eb4d50e371b003f34c3b522c4939826f5dc..8423a1d4ef4a39bb1734b56f8a396d73b264ac9a 100644 +index 5b479ff2abe8cdd5e889803c73a713bc9855bc0b..5954dff2134654bb0ccc3b4c3b51a8e1ca77f6c9 100644 --- a/src/main/java/org/bukkit/inventory/InventoryView.java +++ b/src/main/java/org/bukkit/inventory/InventoryView.java -@@ -271,12 +271,26 @@ public interface InventoryView { +@@ -267,12 +267,26 @@ public interface InventoryView { */ public boolean setProperty(@NotNull Property prop, int value); diff --git a/patches/api/0009-Paper-Plugins.patch b/patches/api/0009-Paper-Plugins.patch index 1cd5d231bdd3..7a96b0031700 100644 --- a/patches/api/0009-Paper-Plugins.patch +++ b/patches/api/0009-Paper-Plugins.patch @@ -1347,10 +1347,10 @@ index 0000000000000000000000000000000000000000..6bf3d212a6156ad9ab0e82d1ca0a04f8 + +} diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index baf49da3dd46039da2f24a4af8b1b8617bb25501..7cf61228754527ddaa6b39b5f1426e0527cdaac9 100644 +index 9ba1a4e838538ecd55f4f8e50ffb0c5f1f474382..d8b346fe0f9634218954fe818d53272a0896af9c 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -137,4 +137,14 @@ public interface UnsafeValues { +@@ -141,4 +141,14 @@ public interface UnsafeValues { @ApiStatus.Internal B get(Registry registry, NamespacedKey key); diff --git a/patches/api/0011-Timings-v2.patch b/patches/api/0011-Timings-v2.patch index 87905001f4ee..a7c06e2704d0 100644 --- a/patches/api/0011-Timings-v2.patch +++ b/patches/api/0011-Timings-v2.patch @@ -2851,10 +2851,10 @@ index 0000000000000000000000000000000000000000..3e61a926620a67daec3af54b72a1b911 + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 87948f6c3b55bbf115561292544e8cf146cd1830..6ecab28705afc0e3652677b516d8a5398e8b2666 100644 +index fe6c43405e3f11272c1ff015f1dcd47129a68d41..8d729fb196d83e01e4652fb1f77f5cab7b57cc31 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -867,7 +867,6 @@ public final class Bukkit { +@@ -870,7 +870,6 @@ public final class Bukkit { */ public static void reload() { server.reload(); @@ -2863,10 +2863,10 @@ index 87948f6c3b55bbf115561292544e8cf146cd1830..6ecab28705afc0e3652677b516d8a539 /** diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index ddbaa7fb174e05533023a2523d67c3d3a6b1b443..f4b2ad91c7a46af5fc16f31369d155e4e3ab3aae 100644 +index fa6ad07214d5e38866bf6bee9139c6c938e9f51a..57c9b560c77a56588870598acb543469040ceec1 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1957,6 +1957,26 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1960,6 +1960,26 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi throw new UnsupportedOperationException("Not supported yet."); } @@ -2894,7 +2894,7 @@ index ddbaa7fb174e05533023a2523d67c3d3a6b1b443..f4b2ad91c7a46af5fc16f31369d155e4 * Sends the component to the player * diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 7cf61228754527ddaa6b39b5f1426e0527cdaac9..9082e67324f810857db26bb89ecea7e9f866f80d 100644 +index d8b346fe0f9634218954fe818d53272a0896af9c..7545e3489474aab3f935095c6057ea2eac1bf84b 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java @@ -40,6 +40,7 @@ public interface UnsafeValues { @@ -2905,7 +2905,7 @@ index 7cf61228754527ddaa6b39b5f1426e0527cdaac9..9082e67324f810857db26bb89ecea7e9 Material toLegacy(Material material); Material fromLegacy(Material material); -@@ -147,4 +148,12 @@ public interface UnsafeValues { +@@ -151,4 +152,12 @@ public interface UnsafeValues { return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); } // Paper end diff --git a/patches/api/0014-Add-getTPS-method.patch b/patches/api/0014-Add-getTPS-method.patch index e7bac768c20c..222b92aec73a 100644 --- a/patches/api/0014-Add-getTPS-method.patch +++ b/patches/api/0014-Add-getTPS-method.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add getTPS method diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index db51751d2dc1ac419e8fac32466ad3a7727fa2fe..99ad0667f4e7e03c2754d9c39f1ebb23c81be5ef 100644 +index d978c72cdbc10792f852a4ba372518073893d02b..5780003631beae773231afe3afc6b834bfe1f84d 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2105,6 +2105,17 @@ public final class Bukkit { +@@ -2108,6 +2108,17 @@ public final class Bukkit { return server.getEntity(uuid); } @@ -27,10 +27,10 @@ index db51751d2dc1ac419e8fac32466ad3a7727fa2fe..99ad0667f4e7e03c2754d9c39f1ebb23 * Get the advancement specified by this key. * diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 638e98416fdf7ac065abe058d625b1c924be5abb..cedd5cb5b3488925405d80441a52239c171c5f3d 100644 +index 8949b8e29ae7f412481291630a5cb7b5b8809842..ba28d9f3213ca4b5f15178dc637bff37a8896edc 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1794,6 +1794,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1797,6 +1797,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @Nullable Entity getEntity(@NotNull UUID uuid); diff --git a/patches/api/0015-Expose-server-build-information.patch b/patches/api/0015-Expose-server-build-information.patch index e1eb350defaf..dc91a4b5d27e 100644 --- a/patches/api/0015-Expose-server-build-information.patch +++ b/patches/api/0015-Expose-server-build-information.patch @@ -230,7 +230,7 @@ index 0000000000000000000000000000000000000000..909617079db61b675cc7b60b44ef96b3 + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 99ad0667f4e7e03c2754d9c39f1ebb23c81be5ef..9b28dcade753bf3d2117d3d2638b529db0e533d4 100644 +index 5780003631beae773231afe3afc6b834bfe1f84d..a005d5f8879262c763d8c4fbd09b9a99810d5e8c 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -110,13 +110,26 @@ public final class Bukkit { @@ -291,7 +291,7 @@ index 99ad0667f4e7e03c2754d9c39f1ebb23c81be5ef..9b28dcade753bf3d2117d3d2638b529d * Gets a view of all currently logged in players. This {@linkplain * Collections#unmodifiableCollection(Collection) view} is a reused diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index cedd5cb5b3488925405d80441a52239c171c5f3d..6e3f48f39bd32537f747dbe5b323f882d1b48b16 100644 +index ba28d9f3213ca4b5f15178dc637bff37a8896edc..8a07f21eeb04fb54032ce377a1478f60303e1824 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -120,6 +120,16 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @@ -312,10 +312,10 @@ index cedd5cb5b3488925405d80441a52239c171c5f3d..6e3f48f39bd32537f747dbe5b323f882 * Gets a view of all currently logged in players. This {@linkplain * Collections#unmodifiableCollection(Collection) view} is a reused diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 9082e67324f810857db26bb89ecea7e9f866f80d..da997507b96908027c49dabc6daf7c787dcad95d 100644 +index 7545e3489474aab3f935095c6057ea2eac1bf84b..6def69b973a76a4cee5aee6431a6538e4c27377d 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -155,5 +155,12 @@ public interface UnsafeValues { +@@ -159,5 +159,12 @@ public interface UnsafeValues { * @return name */ String getTimingsServerName(); diff --git a/patches/api/0019-Expose-server-CommandMap.patch b/patches/api/0019-Expose-server-CommandMap.patch index 55786e0ffbd4..e19fe761d4f6 100644 --- a/patches/api/0019-Expose-server-CommandMap.patch +++ b/patches/api/0019-Expose-server-CommandMap.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose server CommandMap diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 9b28dcade753bf3d2117d3d2638b529db0e533d4..fe074fe9553f61bdd72b64830532a78415348781 100644 +index a005d5f8879262c763d8c4fbd09b9a99810d5e8c..26f3ac9c15ff554becfe8ea53a48f67b2de60ed6 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2334,6 +2334,19 @@ public final class Bukkit { +@@ -2337,6 +2337,19 @@ public final class Bukkit { return server.getUnsafe(); } @@ -29,10 +29,10 @@ index 9b28dcade753bf3d2117d3d2638b529db0e533d4..fe074fe9553f61bdd72b64830532a784 public static Server.Spigot spigot() { return server.spigot(); diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 6e3f48f39bd32537f747dbe5b323f882d1b48b16..9545da2adacaf0bd719c2baef929588cd1042d25 100644 +index 8a07f21eeb04fb54032ce377a1478f60303e1824..d78481bf17818415524f14417caf86d5684b2235 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1814,6 +1814,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1817,6 +1817,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi public double[] getTPS(); // Paper end diff --git a/patches/api/0029-Add-command-to-reload-permissions.yml-and-require-co.patch b/patches/api/0029-Add-command-to-reload-permissions.yml-and-require-co.patch index b7ff894867f9..0f8930de73fe 100644 --- a/patches/api/0029-Add-command-to-reload-permissions.yml-and-require-co.patch +++ b/patches/api/0029-Add-command-to-reload-permissions.yml-and-require-co.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add command to reload permissions.yml and require confirm to diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 4c5327da1468cb1f9af00a99e7e79f578c47ee2a..913141e79a463774d1856f7c34e469cc77ccfcdc 100644 +index bd3fa2bcee24ab7e8f740722f55ed6294fdb294a..d9f84c4a5bc5609e7d9fd0970696a46a32f3f5ff 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2369,6 +2369,13 @@ public final class Bukkit { +@@ -2372,6 +2372,13 @@ public final class Bukkit { public static org.bukkit.command.CommandMap getCommandMap() { return server.getCommandMap(); } @@ -24,10 +24,10 @@ index 4c5327da1468cb1f9af00a99e7e79f578c47ee2a..913141e79a463774d1856f7c34e469cc @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 19b75704ed9eee0c929df417e1e5d0ea3718e2f8..bb0d64b1ff147e63b927b275553d8265bfcd396d 100644 +index 067eb3a5f5676f3b1b3f49a65df9c4054c48a1e7..990d0d02d1bd95886126efe08e8107322e3199d5 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2075,4 +2075,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2078,4 +2078,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @NotNull Spigot spigot(); // Spigot end diff --git a/patches/api/0042-Allow-Reloading-of-Command-Aliases.patch b/patches/api/0042-Allow-Reloading-of-Command-Aliases.patch index b5f012ce4296..41e173a2d0e6 100644 --- a/patches/api/0042-Allow-Reloading-of-Command-Aliases.patch +++ b/patches/api/0042-Allow-Reloading-of-Command-Aliases.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Allow Reloading of Command Aliases Reload the aliases stored in commands.yml diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 913141e79a463774d1856f7c34e469cc77ccfcdc..26fcb119a448f1def8eb5002c41264fa129f1c08 100644 +index d9f84c4a5bc5609e7d9fd0970696a46a32f3f5ff..47c7b0baae47ca263907b0dd70d75f37793517fc 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2376,6 +2376,15 @@ public final class Bukkit { +@@ -2379,6 +2379,15 @@ public final class Bukkit { public static void reloadPermissions() { server.reloadPermissions(); } @@ -26,10 +26,10 @@ index 913141e79a463774d1856f7c34e469cc77ccfcdc..26fcb119a448f1def8eb5002c41264fa @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index bb0d64b1ff147e63b927b275553d8265bfcd396d..a9b22b01b6deba981e84707c5e88981980b8fb65 100644 +index 990d0d02d1bd95886126efe08e8107322e3199d5..ced9203c81477c802983df2f03b4e4efc517519b 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2077,4 +2077,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2080,4 +2080,6 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi // Spigot end void reloadPermissions(); // Paper diff --git a/patches/api/0052-Add-configuration-option-to-prevent-player-names-fro.patch b/patches/api/0052-Add-configuration-option-to-prevent-player-names-fro.patch index 37fcf69d8e52..9a7bbec24b3e 100644 --- a/patches/api/0052-Add-configuration-option-to-prevent-player-names-fro.patch +++ b/patches/api/0052-Add-configuration-option-to-prevent-player-names-fro.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add configuration option to prevent player names from being diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 26fcb119a448f1def8eb5002c41264fa129f1c08..4597eb83b800072c3c2906cdd143c6e2909f89a2 100644 +index 47c7b0baae47ca263907b0dd70d75f37793517fc..72983c3ea04382570c4b52e879dab56702bae55a 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2385,6 +2385,16 @@ public final class Bukkit { +@@ -2388,6 +2388,16 @@ public final class Bukkit { public static boolean reloadCommandAliases() { return server.reloadCommandAliases(); } @@ -27,10 +27,10 @@ index 26fcb119a448f1def8eb5002c41264fa129f1c08..4597eb83b800072c3c2906cdd143c6e2 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index a9b22b01b6deba981e84707c5e88981980b8fb65..fae8fb5261930a24fef889405878432a83db6169 100644 +index ced9203c81477c802983df2f03b4e4efc517519b..0ba391e6a1e585f29930b4111421e99f6eb11b4a 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2079,4 +2079,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2082,4 +2082,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi void reloadPermissions(); // Paper boolean reloadCommandAliases(); // Paper diff --git a/patches/api/0053-Fix-upstream-javadocs.patch b/patches/api/0053-Fix-upstream-javadocs.patch index dfad0db9c9e2..c443b9328b28 100644 --- a/patches/api/0053-Fix-upstream-javadocs.patch +++ b/patches/api/0053-Fix-upstream-javadocs.patch @@ -49,10 +49,10 @@ index a04cde615f8c4bc593f8d9f8f6f1438008aaa707..548f6d28c28d74bed8b58ee828759093 * @param target the target to remove from this list */ diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 4597eb83b800072c3c2906cdd143c6e2909f89a2..5766072d436f8e36e2a3e734c817ecfe899398ce 100644 +index 72983c3ea04382570c4b52e879dab56702bae55a..dec72e92fb9e489d1d04cdf60c2f1d34571f9410 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1535,6 +1535,8 @@ public final class Bukkit { +@@ -1538,6 +1538,8 @@ public final class Bukkit { /** * Gets every player that has ever played on this server. @@ -127,7 +127,7 @@ index 4c9fd558fbf7f57a948fbb7f80f4651048c0fb57..458119a9ef7ce8e1f59bd47caa5b4bc6 * @param statePredicate The predicate which should get used to test if a block should be set or not. * @return true if the tree was created successfully, otherwise false diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index fae8fb5261930a24fef889405878432a83db6169..ba9c7a322f08fcc9df0ebf39720e2e95b275c651 100644 +index 0ba391e6a1e585f29930b4111421e99f6eb11b4a..2f68b766267b53e98dee3054e0a69be8b9cdf70f 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -581,13 +581,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @@ -145,7 +145,7 @@ index fae8fb5261930a24fef889405878432a83db6169..ba9c7a322f08fcc9df0ebf39720e2e95 */ public int getTicksPerSpawns(@NotNull SpawnCategory spawnCategory); -@@ -1295,6 +1292,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1298,6 +1295,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi /** * Gets every player that has ever played on this server. @@ -402,7 +402,7 @@ index 4e1fb0974d061d5bb64899cac576318d2e6f8bf6..539b3527d0c66611e21712f29b90fba9 public int getEntityId(); diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index fffc478312566bc5c36dbacbdd86341d84d50054..8d97cf229ce1d14232d0342121b5db2230795a1d 100644 +index 274f3ccbc39d4d6ff0665abf334d526317275dd0..a7bfaa874cbd3fc8d24fffe2f7f14594b37fa18c 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java @@ -22,6 +22,11 @@ import org.jetbrains.annotations.Nullable; @@ -707,10 +707,10 @@ index a37febd0d4dd5b733e9ee72628fdf9395fec4367..9cee218b9ee14688356f16b1f5851218 */ public class AreaEffectCloudApplyEvent extends EntityEvent implements Cancellable { diff --git a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java -index 330bcc65c1d65c3e59f2763892c90db72bd6757b..394ea92c1021d04e1687b8c12854356265e3d5de 100644 +index 90b287cd2cc6f05bb0c588d8be397cf52a7822de..15cb5ea4b68eca070f73d2b899543274415ad240 100644 --- a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java +++ b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java -@@ -154,11 +154,12 @@ public class CreatureSpawnEvent extends EntitySpawnEvent { +@@ -158,11 +158,12 @@ public class CreatureSpawnEvent extends EntitySpawnEvent { */ DROWNED, /** @@ -792,7 +792,7 @@ index 327876e0ad7dcfeb71d9d22afe1c04bcd71c3bf9..71d664dd89995f088c47d17b38547d53 *
* Note that this event is currently only fired for four specific placements: diff --git a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java -index 01c5e8b71338fbb4b1605e45bf2a2e705188f6b5..c9f395064656dd0126410eb3c6e197baa450c063 100644 +index 31a5515c08c9454d52a0d946d103a2d526c15e48..d743cc5ee34fd7bc5db92f4b17fed9f3aa5ffbcc 100644 --- a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java @@ -133,7 +133,7 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable @@ -804,7 +804,7 @@ index 01c5e8b71338fbb4b1605e45bf2a2e705188f6b5..c9f395064656dd0126410eb3c6e197ba * type. */ ADDED, -@@ -238,7 +238,7 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable +@@ -237,7 +237,7 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable */ SPIDER_SPAWN, /** @@ -1424,7 +1424,7 @@ index f1918027c3a8735b31566856218611656b56db20..476fe14faa39f02444cab8ad95d44010 * @return the currently held item * @see #getItemInMainHand() diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -index 05f1acaac3a49c42f6cf544adb3ffec267c72700..9f9c67e935940833bbfe58e6bfa398e6c86980d5 100644 +index a601bc38e322e5810cf883708541e2d199f09ebb..d89068a37de1dcad0b82dee09cc7829109921a05 100644 --- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java +++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java @@ -24,8 +24,6 @@ public class ShapedRecipe extends CraftingRecipe { diff --git a/patches/api/0057-Basic-PlayerProfile-API.patch b/patches/api/0057-Basic-PlayerProfile-API.patch index ffeb61122173..1161dbaabf61 100644 --- a/patches/api/0057-Basic-PlayerProfile-API.patch +++ b/patches/api/0057-Basic-PlayerProfile-API.patch @@ -327,10 +327,10 @@ index 0000000000000000000000000000000000000000..8f913a078dd692a9feafb98a6e6c9583 + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 5766072d436f8e36e2a3e734c817ecfe899398ce..ce20f1231b7998f8c4e1bf85d815661984c4f45c 100644 +index dec72e92fb9e489d1d04cdf60c2f1d34571f9410..dcf6b2d04f9e1bc7466feda22069423d638fb4b3 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2397,6 +2397,89 @@ public final class Bukkit { +@@ -2400,6 +2400,89 @@ public final class Bukkit { public static boolean suggestPlayerNamesWhenNullTabCompletions() { return server.suggestPlayerNamesWhenNullTabCompletions(); } @@ -421,10 +421,10 @@ index 5766072d436f8e36e2a3e734c817ecfe899398ce..ce20f1231b7998f8c4e1bf85d8156619 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index ba9c7a322f08fcc9df0ebf39720e2e95b275c651..d699dd95dfdcebd22ab7e718b181ffcffe0c919e 100644 +index 2f68b766267b53e98dee3054e0a69be8b9cdf70f..7a1b80e8d02f23c5d246c3032e5ced909f10bd41 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2087,5 +2087,80 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2090,5 +2090,80 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @return true if player names should be suggested */ boolean suggestPlayerNamesWhenNullTabCompletions(); diff --git a/patches/api/0059-Shoulder-Entities-Release-API.patch b/patches/api/0059-Shoulder-Entities-Release-API.patch index d02f2a3521fc..b7f5537f7971 100644 --- a/patches/api/0059-Shoulder-Entities-Release-API.patch +++ b/patches/api/0059-Shoulder-Entities-Release-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Shoulder Entities Release API diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 8d97cf229ce1d14232d0342121b5db2230795a1d..c426bdea5ef71a095cf2af9a8a83a162db3c05b7 100644 +index a7bfaa874cbd3fc8d24fffe2f7f14594b37fa18c..8cc6f8547380d567aef7910ef309193bd79ced09 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -329,6 +329,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -335,6 +335,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder */ public int getExpToLevel(); diff --git a/patches/api/0089-Player.setPlayerProfile-API.patch b/patches/api/0089-Player.setPlayerProfile-API.patch index a12782792efe..ad5dc34a8985 100644 --- a/patches/api/0089-Player.setPlayerProfile-API.patch +++ b/patches/api/0089-Player.setPlayerProfile-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Player.setPlayerProfile API This can be useful for changing name or skins after a player has logged in. diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index ce20f1231b7998f8c4e1bf85d815661984c4f45c..52123fd754530a9a5a22c81cc5ad763d3e2355b2 100644 +index dcf6b2d04f9e1bc7466feda22069423d638fb4b3..da18fbc38976c601da7781b488449da7d724160f 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1377,8 +1377,10 @@ public final class Bukkit { +@@ -1380,8 +1380,10 @@ public final class Bukkit { * @return the new PlayerProfile * @throws IllegalArgumentException if both the unique id is * null and the name is null or blank @@ -20,7 +20,7 @@ index ce20f1231b7998f8c4e1bf85d815661984c4f45c..52123fd754530a9a5a22c81cc5ad763d public static PlayerProfile createPlayerProfile(@Nullable UUID uniqueId, @Nullable String name) { return server.createPlayerProfile(uniqueId, name); } -@@ -1389,8 +1391,10 @@ public final class Bukkit { +@@ -1392,8 +1394,10 @@ public final class Bukkit { * @param uniqueId the unique id * @return the new PlayerProfile * @throws IllegalArgumentException if the unique id is null @@ -31,7 +31,7 @@ index ce20f1231b7998f8c4e1bf85d815661984c4f45c..52123fd754530a9a5a22c81cc5ad763d public static PlayerProfile createPlayerProfile(@NotNull UUID uniqueId) { return server.createPlayerProfile(uniqueId); } -@@ -1402,8 +1406,10 @@ public final class Bukkit { +@@ -1405,8 +1409,10 @@ public final class Bukkit { * @return the new PlayerProfile * @throws IllegalArgumentException if the name is null or * blank @@ -56,10 +56,10 @@ index ff59479f4782ac7726504aab239de79fdc840cde..abbf3d6f11350ab2dd47a277771d9f46 /** * Checks if this player has had their profile banned. diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index d699dd95dfdcebd22ab7e718b181ffcffe0c919e..ce29d2d3c2fd06a09eba2147c92b3387f0a81153 100644 +index 7a1b80e8d02f23c5d246c3032e5ced909f10bd41..01c052d90bbdad3fc374eb9c8e0a5133b8b624e8 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1164,8 +1164,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1167,8 +1167,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @return the new PlayerProfile * @throws IllegalArgumentException if both the unique id is * null and the name is null or blank @@ -70,7 +70,7 @@ index d699dd95dfdcebd22ab7e718b181ffcffe0c919e..ce29d2d3c2fd06a09eba2147c92b3387 PlayerProfile createPlayerProfile(@Nullable UUID uniqueId, @Nullable String name); /** -@@ -1174,8 +1176,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1177,8 +1179,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @param uniqueId the unique id * @return the new PlayerProfile * @throws IllegalArgumentException if the unique id is null @@ -81,7 +81,7 @@ index d699dd95dfdcebd22ab7e718b181ffcffe0c919e..ce29d2d3c2fd06a09eba2147c92b3387 PlayerProfile createPlayerProfile(@NotNull UUID uniqueId); /** -@@ -1185,8 +1189,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1188,8 +1192,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @return the new PlayerProfile * @throws IllegalArgumentException if the name is null or * blank diff --git a/patches/api/0090-getPlayerUniqueId-API.patch b/patches/api/0090-getPlayerUniqueId-API.patch index 2715d60c2bed..4ded35b02d4f 100644 --- a/patches/api/0090-getPlayerUniqueId-API.patch +++ b/patches/api/0090-getPlayerUniqueId-API.patch @@ -9,10 +9,10 @@ In Offline Mode, will return an Offline UUID This is a more performant way to obtain a UUID for a name than loading an OfflinePlayer diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 52123fd754530a9a5a22c81cc5ad763d3e2355b2..5c0f610a45b6dc97f68f90a54f69b4c787157ef3 100644 +index da18fbc38976c601da7781b488449da7d724160f..28b86658aea14b33470508944d8626b23c65bba2 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -750,6 +750,20 @@ public final class Bukkit { +@@ -753,6 +753,20 @@ public final class Bukkit { return server.getPlayer(id); } @@ -34,10 +34,10 @@ index 52123fd754530a9a5a22c81cc5ad763d3e2355b2..5c0f610a45b6dc97f68f90a54f69b4c7 * Gets the plugin manager for interfacing with plugins. * diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index ce29d2d3c2fd06a09eba2147c92b3387f0a81153..b26cbe2246722ff5d8ffad6a5734478146e3e192 100644 +index 01c052d90bbdad3fc374eb9c8e0a5133b8b624e8..5c6c9f714097dfaead0093d752f1b373b70a75eb 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -630,6 +630,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -633,6 +633,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @Nullable public Player getPlayer(@NotNull UUID id); diff --git a/patches/api/0092-Add-openSign-method-to-HumanEntity.patch b/patches/api/0092-Add-openSign-method-to-HumanEntity.patch index 125fad56adfe..d519918aba6e 100644 --- a/patches/api/0092-Add-openSign-method-to-HumanEntity.patch +++ b/patches/api/0092-Add-openSign-method-to-HumanEntity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add openSign method to HumanEntity diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index c426bdea5ef71a095cf2af9a8a83a162db3c05b7..2308fa3ca898bcb6c0ac2d4853f82a3398bf51f3 100644 +index 8cc6f8547380d567aef7910ef309193bd79ced09..48bb08cc7c0af6ebb905d1e175ada0fd7944ca48 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -490,6 +490,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -496,6 +496,26 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder */ @Deprecated public void setShoulderEntityRight(@Nullable Entity entity); diff --git a/patches/api/0114-LivingEntity-Active-Item-API.patch b/patches/api/0114-LivingEntity-Active-Item-API.patch index 268d315eb2b8..f98f5d9a7e63 100644 --- a/patches/api/0114-LivingEntity-Active-Item-API.patch +++ b/patches/api/0114-LivingEntity-Active-Item-API.patch @@ -9,10 +9,10 @@ such as a bow or eating food. Co-authored-by: Jake Potrebic diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 2308fa3ca898bcb6c0ac2d4853f82a3398bf51f3..15115b1049bc5053796b84539acbf576bcba1a5f 100644 +index 48bb08cc7c0af6ebb905d1e175ada0fd7944ca48..ee3086661e11d3d8faec30590be7131648d3b82a 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -319,7 +319,9 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -325,7 +325,9 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder * blocking). * * @return Whether their hand is raised diff --git a/patches/api/0117-InventoryCloseEvent-Reason-API.patch b/patches/api/0117-InventoryCloseEvent-Reason-API.patch index 6c7189a322e0..ed0568548a69 100644 --- a/patches/api/0117-InventoryCloseEvent-Reason-API.patch +++ b/patches/api/0117-InventoryCloseEvent-Reason-API.patch @@ -7,10 +7,10 @@ Allows you to determine why an inventory was closed, enabling plugin developers to "confirm" things based on if it was player triggered close or not. diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 15115b1049bc5053796b84539acbf576bcba1a5f..c66130be13bf01b5834a6391864b865c0123fa5c 100644 +index ee3086661e11d3d8faec30590be7131648d3b82a..25cd03f2f3dc0aaa67173c0f3ebfe56402489e24 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -179,6 +179,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -185,6 +185,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder */ public void closeInventory(); diff --git a/patches/api/0135-Add-More-Creeper-API.patch b/patches/api/0135-Add-More-Creeper-API.patch index 2ea104b55205..fae3db5746c3 100644 --- a/patches/api/0135-Add-More-Creeper-API.patch +++ b/patches/api/0135-Add-More-Creeper-API.patch @@ -71,13 +71,13 @@ index 0000000000000000000000000000000000000000..e86500337f26fcb6bb04545c68c67df3 + } +} diff --git a/src/main/java/org/bukkit/entity/Creeper.java b/src/main/java/org/bukkit/entity/Creeper.java -index 5793193d93d76a062fd0431475c269c4978ec993..e144f618702122bf28ebedc5cb8ce0f6ef27c107 100644 +index e440b06f358e7edc87254e46d1a2002216ebbab1..5e750f4043fdf5ac9836056a015148df92aed067 100644 --- a/src/main/java/org/bukkit/entity/Creeper.java +++ b/src/main/java/org/bukkit/entity/Creeper.java -@@ -87,4 +87,20 @@ public interface Creeper extends Monster { - * griefing gamerule. +@@ -112,4 +112,20 @@ public interface Creeper extends Monster { */ - public void ignite(); + @Nullable + public Entity getIgniter(); + // Paper start + + /** diff --git a/patches/api/0154-Make-the-default-permission-message-configurable.patch b/patches/api/0154-Make-the-default-permission-message-configurable.patch index 10b063f12569..f796979a13fa 100644 --- a/patches/api/0154-Make-the-default-permission-message-configurable.patch +++ b/patches/api/0154-Make-the-default-permission-message-configurable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make the default permission message configurable diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 5c0f610a45b6dc97f68f90a54f69b4c787157ef3..fb143a39f81ca7f14688ee3515a06256feac0f80 100644 +index 28b86658aea14b33470508944d8626b23c65bba2..577b4b89b50441572f0edd9325047c38e25e782e 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2418,6 +2418,28 @@ public final class Bukkit { +@@ -2421,6 +2421,28 @@ public final class Bukkit { return server.suggestPlayerNamesWhenNullTabCompletions(); } @@ -38,10 +38,10 @@ index 5c0f610a45b6dc97f68f90a54f69b4c787157ef3..fb143a39f81ca7f14688ee3515a06256 * Creates a PlayerProfile for the specified uuid, with name as null. * diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index b26cbe2246722ff5d8ffad6a5734478146e3e192..c1a1baa2c79ad48b210e770f198ca9a2d7815df4 100644 +index 5c6c9f714097dfaead0093d752f1b373b70a75eb..08f6f85388e4c3e3aae40f709109f8706a400675 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2106,6 +2106,23 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2109,6 +2109,23 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ boolean suggestPlayerNamesWhenNullTabCompletions(); diff --git a/patches/api/0160-Add-ItemStack-Recipe-API-helper-methods.patch b/patches/api/0160-Add-ItemStack-Recipe-API-helper-methods.patch index 817b9a2a623b..14e94043d25f 100644 --- a/patches/api/0160-Add-ItemStack-Recipe-API-helper-methods.patch +++ b/patches/api/0160-Add-ItemStack-Recipe-API-helper-methods.patch @@ -22,10 +22,10 @@ index a98fc2ffdae1a2f8f3a312bed95268e105f7f791..91bfeffcdbe47208c7d0ddbe013cd0f1 public static class ExactChoice implements RecipeChoice { diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -index 71e494177473c62449aafda1699b26a0c4c81a68..97d5d9c6347bc401e3f4ab7c0ba1391ad5b0449a 100644 +index 1ef513d4d03ce677ee9c77b91e2cc5553ab91e0b..1012656948e9bf2aa18867cc2409616f3f21501e 100644 --- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java +++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -@@ -168,6 +168,13 @@ public class ShapedRecipe extends CraftingRecipe { +@@ -179,6 +179,13 @@ public class ShapedRecipe extends CraftingRecipe { return this; } diff --git a/patches/api/0166-Fix-Spigot-annotation-mistakes.patch b/patches/api/0166-Fix-Spigot-annotation-mistakes.patch index c781240a60a3..a496266a07bd 100644 --- a/patches/api/0166-Fix-Spigot-annotation-mistakes.patch +++ b/patches/api/0166-Fix-Spigot-annotation-mistakes.patch @@ -40,10 +40,10 @@ index dadff073abb2dec39111e677ec77ffdb2b7ff9a9..042d1d932a33022e4fc873652f70dc6e public static Art getById(int id) { return BY_ID.get(id); diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index fb143a39f81ca7f14688ee3515a06256feac0f80..7b29a19610dbdc99e3662f70a8a291e6203edd1a 100644 +index 577b4b89b50441572f0edd9325047c38e25e782e..949ffc320502e46493183cc3ef621d9c4edbe7d6 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -880,9 +880,8 @@ public final class Bukkit { +@@ -883,9 +883,8 @@ public final class Bukkit { * * @param id the id of the map to get * @return a map view if it exists, or null otherwise @@ -54,7 +54,7 @@ index fb143a39f81ca7f14688ee3515a06256feac0f80..7b29a19610dbdc99e3662f70a8a291e6 @Nullable public static MapView getMap(int id) { return server.getMap(id); -@@ -961,8 +960,14 @@ public final class Bukkit { +@@ -964,8 +963,14 @@ public final class Bukkit { * Returns the primary logger associated with this server instance. * * @return Logger associated with this server @@ -69,7 +69,7 @@ index fb143a39f81ca7f14688ee3515a06256feac0f80..7b29a19610dbdc99e3662f70a8a291e6 public static Logger getLogger() { return server.getLogger(); } -@@ -1359,10 +1364,8 @@ public final class Bukkit { +@@ -1362,10 +1367,8 @@ public final class Bukkit { * @param name the name the player to retrieve * @return an offline player * @see #getOfflinePlayer(java.util.UUID) @@ -81,7 +81,7 @@ index fb143a39f81ca7f14688ee3515a06256feac0f80..7b29a19610dbdc99e3662f70a8a291e6 @NotNull public static OfflinePlayer getOfflinePlayer(@NotNull String name) { return server.getOfflinePlayer(name); -@@ -1975,7 +1978,7 @@ public final class Bukkit { +@@ -1978,7 +1981,7 @@ public final class Bukkit { * * @return the scoreboard manager or null if no worlds are loaded. */ @@ -498,10 +498,10 @@ index 6277451c3c6c551078c237cd767b6d70c4f585ea..7d33b3e2f81c14d3aeb800b39e782383 CRACKED(0x0), GLYPHED(0x1), diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index c1a1baa2c79ad48b210e770f198ca9a2d7815df4..75b3295a5544626d28c57b317d95db90722de719 100644 +index 08f6f85388e4c3e3aae40f709109f8706a400675..c6ebdefe940e5e3ab04aac0f22924ef5d876d328 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -741,9 +741,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -744,9 +744,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * * @param id the id of the map to get * @return a map view if it exists, or null otherwise @@ -512,7 +512,7 @@ index c1a1baa2c79ad48b210e770f198ca9a2d7815df4..75b3295a5544626d28c57b317d95db90 @Nullable public MapView getMap(int id); -@@ -810,8 +809,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -813,8 +812,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * Returns the primary logger associated with this server instance. * * @return Logger associated with this server @@ -527,7 +527,7 @@ index c1a1baa2c79ad48b210e770f198ca9a2d7815df4..75b3295a5544626d28c57b317d95db90 public Logger getLogger(); /** -@@ -1148,10 +1153,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1151,10 +1156,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @param name the name the player to retrieve * @return an offline player * @see #getOfflinePlayer(java.util.UUID) @@ -539,7 +539,7 @@ index c1a1baa2c79ad48b210e770f198ca9a2d7815df4..75b3295a5544626d28c57b317d95db90 @NotNull public OfflinePlayer getOfflinePlayer(@NotNull String name); -@@ -1669,7 +1672,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1672,7 +1675,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * * @return the scoreboard manager or null if no worlds are loaded. */ @@ -1091,10 +1091,10 @@ index f2edd4a9357832e9dec3fb0aafa006335d7b289b..f05ce4fd6c4bbd79edc5f65e7edd1e4a } diff --git a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java -index c9f395064656dd0126410eb3c6e197baa450c063..c95943a0c6a2cc7685b0e2601460d92fa1b4b2f5 100644 +index d743cc5ee34fd7bc5db92f4b17fed9f3aa5ffbcc..8fdfcbc7d20fe0af6b220ab94516247093637621 100644 --- a/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java +++ b/src/main/java/org/bukkit/event/entity/EntityPotionEffectEvent.java -@@ -219,7 +219,10 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable +@@ -218,7 +218,10 @@ public class EntityPotionEffectEvent extends EntityEvent implements Cancellable MILK, /** * When a player gets bad omen after killing a patrol captain. @@ -1497,10 +1497,10 @@ index f1a48eab1a357ae64545e1f1dc941c383cff8707..466d1bd7089b76f48f953e1a51c611ec /** * Checks if the inventory contains any ItemStacks with the given diff --git a/src/main/java/org/bukkit/inventory/InventoryView.java b/src/main/java/org/bukkit/inventory/InventoryView.java -index 8423a1d4ef4a39bb1734b56f8a396d73b264ac9a..1e50dba6bb8753e6c1adff59ee0ff93adf3bfd4f 100644 +index 5954dff2134654bb0ccc3b4c3b51a8e1ca77f6c9..72f93377b60a3b6a08b8c8264ee7313e89c15da0 100644 --- a/src/main/java/org/bukkit/inventory/InventoryView.java +++ b/src/main/java/org/bukkit/inventory/InventoryView.java -@@ -125,9 +125,9 @@ public interface InventoryView { +@@ -121,9 +121,9 @@ public interface InventoryView { * Gets the id of this view. * * @return the id of this view @@ -1512,7 +1512,7 @@ index 8423a1d4ef4a39bb1734b56f8a396d73b264ac9a..1e50dba6bb8753e6c1adff59ee0ff93a public int getId() { return id; } -@@ -197,10 +197,10 @@ public interface InventoryView { +@@ -193,10 +193,10 @@ public interface InventoryView { /** * Get the item on the cursor of one of the viewing players. * @@ -1627,12 +1627,12 @@ index 476fe14faa39f02444cab8ad95d4401033dc6938..2c54660dc1fbc7c1232096797a23cae1 /** diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -index 97d5d9c6347bc401e3f4ab7c0ba1391ad5b0449a..da878c6d4928ddbc16b50ace86d992685a2b7873 100644 +index 1012656948e9bf2aa18867cc2409616f3f21501e..aa3b3070126f1c492f004ec7599eeb379b58f207 100644 --- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java +++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -@@ -100,8 +100,10 @@ public class ShapedRecipe extends CraftingRecipe { - * @param ingredient The ingredient. +@@ -106,8 +106,10 @@ public class ShapedRecipe extends CraftingRecipe { * @return The changed recipe, so you can chain calls. + * @throws IllegalArgumentException if the {@code key} is a space character * @throws IllegalArgumentException if the {@code key} does not appear in the shape. + * @deprecated use {@link #setIngredient(char, RecipeChoice)} */ @@ -1641,7 +1641,7 @@ index 97d5d9c6347bc401e3f4ab7c0ba1391ad5b0449a..da878c6d4928ddbc16b50ace86d99268 public ShapedRecipe setIngredient(char key, @NotNull MaterialData ingredient) { return setIngredient(key, ingredient.getItemType(), ingredient.getData()); } -@@ -179,7 +181,9 @@ public class ShapedRecipe extends CraftingRecipe { +@@ -190,7 +192,9 @@ public class ShapedRecipe extends CraftingRecipe { * Get a copy of the ingredients map. * * @return The mapping of character to ingredients. diff --git a/patches/api/0170-Mob-Spawner-API-Enhancements.patch b/patches/api/0170-Mob-Spawner-API-Enhancements.patch index 4607e8b4bf3a..c7d05493f661 100644 --- a/patches/api/0170-Mob-Spawner-API-Enhancements.patch +++ b/patches/api/0170-Mob-Spawner-API-Enhancements.patch @@ -4,14 +4,14 @@ Date: Fri, 19 Apr 2019 12:41:19 -0500 Subject: [PATCH] Mob Spawner API Enhancements -diff --git a/src/main/java/org/bukkit/block/CreatureSpawner.java b/src/main/java/org/bukkit/block/CreatureSpawner.java -index c33f6573a9cb0a1516539a1947760a093aa08051..1896adcb15479eb8f26fe7185e4755ca7271a75a 100644 ---- a/src/main/java/org/bukkit/block/CreatureSpawner.java -+++ b/src/main/java/org/bukkit/block/CreatureSpawner.java -@@ -277,4 +277,30 @@ public interface CreatureSpawner extends TileState { +diff --git a/src/main/java/org/bukkit/spawner/Spawner.java b/src/main/java/org/bukkit/spawner/Spawner.java +index c595c44698cd3c6379e83248ed3a05e325cadc7f..640767bd16a5406b1f7093c1f6bb7dbc46051b5a 100644 +--- a/src/main/java/org/bukkit/spawner/Spawner.java ++++ b/src/main/java/org/bukkit/spawner/Spawner.java +@@ -107,4 +107,30 @@ public interface Spawner extends BaseSpawner { + * @param maxNearbyEntities the maximum number of nearby, similar, entities */ - @NotNull - public List getPotentialSpawns(); + public void setMaxNearbyEntities(int maxNearbyEntities); + + // Paper start + /** diff --git a/patches/api/0174-Expose-the-internal-current-tick.patch b/patches/api/0174-Expose-the-internal-current-tick.patch index f080acd15579..df627aaad7af 100644 --- a/patches/api/0174-Expose-the-internal-current-tick.patch +++ b/patches/api/0174-Expose-the-internal-current-tick.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose the internal current tick diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 7b29a19610dbdc99e3662f70a8a291e6203edd1a..21f7d4c0e62058df9e8e0d37886e24649a7fab67 100644 +index 949ffc320502e46493183cc3ef621d9c4edbe7d6..594055b26e166e8e7aae0a98688b4ee5f93f5b2a 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2525,6 +2525,10 @@ public final class Bukkit { +@@ -2528,6 +2528,10 @@ public final class Bukkit { public static com.destroystokyo.paper.profile.PlayerProfile createProfileExact(@Nullable UUID uuid, @Nullable String name) { return server.createProfileExact(uuid, name); } @@ -20,10 +20,10 @@ index 7b29a19610dbdc99e3662f70a8a291e6203edd1a..21f7d4c0e62058df9e8e0d37886e2464 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 75b3295a5544626d28c57b317d95db90722de719..5889209e9855d26f07d4cb4b8f9d448fd31e4c87 100644 +index c6ebdefe940e5e3ab04aac0f22924ef5d876d328..6363a5b978679435fe9d618326ad54bdc43be895 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2200,5 +2200,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2203,5 +2203,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ @NotNull com.destroystokyo.paper.profile.PlayerProfile createProfileExact(@Nullable UUID uuid, @Nullable String name); diff --git a/patches/api/0180-Add-tick-times-API.patch b/patches/api/0180-Add-tick-times-API.patch index 29301f813d6e..b6569c4fb837 100644 --- a/patches/api/0180-Add-tick-times-API.patch +++ b/patches/api/0180-Add-tick-times-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add tick times API diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 21f7d4c0e62058df9e8e0d37886e24649a7fab67..b9b4a7574763b0a22d1f6faf6170eb127d488b18 100644 +index 594055b26e166e8e7aae0a98688b4ee5f93f5b2a..b84326b7831829cfa10c31073c6a2de56f86ccd6 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2191,6 +2191,25 @@ public final class Bukkit { +@@ -2194,6 +2194,25 @@ public final class Bukkit { public static double[] getTPS() { return server.getTPS(); } @@ -35,10 +35,10 @@ index 21f7d4c0e62058df9e8e0d37886e24649a7fab67..b9b4a7574763b0a22d1f6faf6170eb12 /** diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 5889209e9855d26f07d4cb4b8f9d448fd31e4c87..d52c81212187a1aea1e666ba2f16bbf273a23594 100644 +index 6363a5b978679435fe9d618326ad54bdc43be895..b128ed4111c6c128c71095e757e57660f61f4f59 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1856,6 +1856,21 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1859,6 +1859,21 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ @NotNull public double[] getTPS(); diff --git a/patches/api/0181-Expose-MinecraftServer-isRunning.patch b/patches/api/0181-Expose-MinecraftServer-isRunning.patch index 4523ddefdcad..87da5bf511a8 100644 --- a/patches/api/0181-Expose-MinecraftServer-isRunning.patch +++ b/patches/api/0181-Expose-MinecraftServer-isRunning.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Expose MinecraftServer#isRunning This allows for plugins to detect if the server is actually turning off in onDisable rather than just plugins reloading. diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index b9b4a7574763b0a22d1f6faf6170eb127d488b18..eaf1cd1b1b74df33f9b4a0809a9570181c67aebe 100644 +index b84326b7831829cfa10c31073c6a2de56f86ccd6..54626b927444ab3fc6b7d9ac9e326ff368b0cd25 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2548,6 +2548,15 @@ public final class Bukkit { +@@ -2551,6 +2551,15 @@ public final class Bukkit { public static int getCurrentTick() { return server.getCurrentTick(); } @@ -26,10 +26,10 @@ index b9b4a7574763b0a22d1f6faf6170eb127d488b18..eaf1cd1b1b74df33f9b4a0809a957018 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index d52c81212187a1aea1e666ba2f16bbf273a23594..1d11fd9a7283d529307bdb74603f03befff07d16 100644 +index b128ed4111c6c128c71095e757e57660f61f4f59..0fa9510db6c81e2c712090e1fc7fc56305af8892 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2222,5 +2222,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2225,5 +2225,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @return Current tick */ int getCurrentTick(); diff --git a/patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch index f23046130941..48586e130cab 100644 --- a/patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch +++ b/patches/api/0182-Add-Raw-Byte-ItemStack-Serialization.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add Raw Byte ItemStack Serialization Serializes using NBT which is safer for server data migrations than bukkits format. diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index da997507b96908027c49dabc6daf7c787dcad95d..cb7aef53cbffc76dea9fec28445ea8aefcb29d62 100644 +index 6def69b973a76a4cee5aee6431a6538e4c27377d..601d7171d182f56442b1dcea8429737ef3909e84 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -162,5 +162,9 @@ public interface UnsafeValues { +@@ -166,5 +166,9 @@ public interface UnsafeValues { default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); } diff --git a/patches/api/0187-Add-Mob-Goal-API.patch b/patches/api/0187-Add-Mob-Goal-API.patch index c3cd7426b86b..4cc271dda3b8 100644 --- a/patches/api/0187-Add-Mob-Goal-API.patch +++ b/patches/api/0187-Add-Mob-Goal-API.patch @@ -226,10 +226,10 @@ index 0000000000000000000000000000000000000000..e21f7574763dd4f13794f91bbef192ef + Collection> getRunningGoalsWithout(@NotNull T mob, @NotNull GoalType type); +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index eaf1cd1b1b74df33f9b4a0809a9570181c67aebe..5626d424e2d05931134a6fa7e14c8ae9d5c71ee8 100644 +index 54626b927444ab3fc6b7d9ac9e326ff368b0cd25..1a671331ec4ab21430d7d52e9a4f45510ef39944 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2557,6 +2557,16 @@ public final class Bukkit { +@@ -2560,6 +2560,16 @@ public final class Bukkit { public static boolean isStopping() { return server.isStopping(); } @@ -247,10 +247,10 @@ index eaf1cd1b1b74df33f9b4a0809a9570181c67aebe..5626d424e2d05931134a6fa7e14c8ae9 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 1d11fd9a7283d529307bdb74603f03befff07d16..edfd016d7dd516c253444c8efa22cf92352da283 100644 +index 0fa9510db6c81e2c712090e1fc7fc56305af8892..7dbd9b32e96c015e3ed757ea0fa7e2bfcf4af85e 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2229,5 +2229,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2232,5 +2232,13 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @return true if server is in the process of being shutdown */ boolean isStopping(); diff --git a/patches/api/0190-Potential-bed-API.patch b/patches/api/0190-Potential-bed-API.patch index a842554f354b..42350ac7bd68 100644 --- a/patches/api/0190-Potential-bed-API.patch +++ b/patches/api/0190-Potential-bed-API.patch @@ -8,10 +8,10 @@ Adds a new method to fetch the location of a player's bed without generating any getPotentialBedLocation - Gets the last known location of a player's bed. This does not preform any check if the bed is still valid and does not load any chunks. diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index c66130be13bf01b5834a6391864b865c0123fa5c..2557ddcc0528d4f9d811883b3ddc61148ebc3998 100644 +index 25cd03f2f3dc0aaa67173c0f3ebfe56402489e24..ccaaf2b6f6424ec7c7d298ceabdc3e60a7917705 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -269,6 +269,19 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -275,6 +275,19 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder */ public int getSleepTicks(); diff --git a/patches/api/0204-Add-additional-open-container-api-to-HumanEntity.patch b/patches/api/0204-Add-additional-open-container-api-to-HumanEntity.patch index 43e6937d0599..c81c83391ce9 100644 --- a/patches/api/0204-Add-additional-open-container-api-to-HumanEntity.patch +++ b/patches/api/0204-Add-additional-open-container-api-to-HumanEntity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add additional open container api to HumanEntity diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 2557ddcc0528d4f9d811883b3ddc61148ebc3998..5ecfb98540c00da05b13bc5370debb89c52cc76f 100644 +index ccaaf2b6f6424ec7c7d298ceabdc3e60a7917705..b980d55b68ed9da78c5cd19f369bb00dccbf08e1 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -174,6 +174,92 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -180,6 +180,92 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder @Nullable public InventoryView openMerchant(@NotNull Merchant merchant, boolean force); diff --git a/patches/api/0205-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/api/0205-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch index 01127fef5bd6..4360d72fd43b 100644 --- a/patches/api/0205-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ b/patches/api/0205-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Expose the Entity Counter to allow plugins to use valid and diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index cb7aef53cbffc76dea9fec28445ea8aefcb29d62..fb1efc7dfcfbfb823c8ad8fe2943adb99104aefe 100644 +index 601d7171d182f56442b1dcea8429737ef3909e84..460b94538a990a5d136c0c07166887940347c6e2 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -166,5 +166,12 @@ public interface UnsafeValues { +@@ -170,5 +170,12 @@ public interface UnsafeValues { byte[] serializeItem(ItemStack item); ItemStack deserializeItem(byte[] data); diff --git a/patches/api/0209-Add-getOfflinePlayerIfCached-String.patch b/patches/api/0209-Add-getOfflinePlayerIfCached-String.patch index 52181f0970b5..f105fefb0c98 100644 --- a/patches/api/0209-Add-getOfflinePlayerIfCached-String.patch +++ b/patches/api/0209-Add-getOfflinePlayerIfCached-String.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add getOfflinePlayerIfCached(String) diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 5626d424e2d05931134a6fa7e14c8ae9d5c71ee8..188280a8fdf35a70a5a358f8cfe7cf44f05855b1 100644 +index 1a671331ec4ab21430d7d52e9a4f45510ef39944..e0f652117e585882693736de8165ae9c689e1d68 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1371,6 +1371,27 @@ public final class Bukkit { +@@ -1374,6 +1374,27 @@ public final class Bukkit { return server.getOfflinePlayer(name); } @@ -37,10 +37,10 @@ index 5626d424e2d05931134a6fa7e14c8ae9d5c71ee8..188280a8fdf35a70a5a358f8cfe7cf44 * Gets the player by the given UUID, regardless if they are offline or * online. diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index edfd016d7dd516c253444c8efa22cf92352da283..076ed338c2f3230be30225a48e3c72dc894cf70a 100644 +index 7dbd9b32e96c015e3ed757ea0fa7e2bfcf4af85e..90111a9ae0b7bdd6e46e869398dc6b9898b5f87e 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1158,6 +1158,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1161,6 +1161,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @NotNull public OfflinePlayer getOfflinePlayer(@NotNull String name); diff --git a/patches/api/0220-Expose-LivingEntity-hurt-direction.patch b/patches/api/0220-Expose-LivingEntity-hurt-direction.patch index 2dc78a669d97..4d2cb26c38ad 100644 --- a/patches/api/0220-Expose-LivingEntity-hurt-direction.patch +++ b/patches/api/0220-Expose-LivingEntity-hurt-direction.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose LivingEntity hurt direction diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 5ecfb98540c00da05b13bc5370debb89c52cc76f..083d5798ccc7f37c6df5e234c7ef233202102b8f 100644 +index b980d55b68ed9da78c5cd19f369bb00dccbf08e1..4d6ceca22d98a3e46aa26ef26176c5417a5ccf35 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -348,6 +348,16 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -354,6 +354,16 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder */ public void setCooldown(@NotNull Material material, int ticks); diff --git a/patches/api/0236-Add-RegistryAccess-for-managing-registries.patch b/patches/api/0236-Add-RegistryAccess-for-managing-registries.patch index 841078a11047..768538fece26 100644 --- a/patches/api/0236-Add-RegistryAccess-for-managing-registries.patch +++ b/patches/api/0236-Add-RegistryAccess-for-managing-registries.patch @@ -190,10 +190,10 @@ index 791813220b2504214b1adecc69093cd600fb0f8c..47fe5b0d5d031110c27210a0a256c260 final RegistryKey registryKey = createInternal(key); REGISTRY_KEYS.add(registryKey); diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 188280a8fdf35a70a5a358f8cfe7cf44f05855b1..ceaa901fa830e904d6ac7a1727d1e7d185107e11 100644 +index e0f652117e585882693736de8165ae9c689e1d68..fbe14c327ee9c1ac07893853ca7c699e81225281 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2407,8 +2407,11 @@ public final class Bukkit { +@@ -2410,8 +2410,11 @@ public final class Bukkit { * @param tClass of the registry to get * @param type of the registry * @return the corresponding registry or null if not present @@ -339,10 +339,10 @@ index 3effaea369d9c7a6a22979fbfc270f55f9f25cf2..93e898c14728491a59bb2d08aff0dd67 * Get the object by its key. * diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 076ed338c2f3230be30225a48e3c72dc894cf70a..fd3686688862fccc9989457cf3c1aaff777c66be 100644 +index 90111a9ae0b7bdd6e46e869398dc6b9898b5f87e..943f8881ea23481ea5d5125b6ec7c9c6f763f0b0 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2056,8 +2056,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2059,8 +2059,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @param tClass of the registry to get * @param type of the registry * @return the corresponding registry or null if not present diff --git a/patches/api/0253-Expand-world-key-API.patch b/patches/api/0253-Expand-world-key-API.patch index b43164495f43..cf5a0e6246a7 100644 --- a/patches/api/0253-Expand-world-key-API.patch +++ b/patches/api/0253-Expand-world-key-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expand world key API diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index ceaa901fa830e904d6ac7a1727d1e7d185107e11..a60b1d57904eefeb832ab93fb0e556de9409e5ae 100644 +index fbe14c327ee9c1ac07893853ca7c699e81225281..a2ced20efd2c6be2fe63d80f444c8cb608c37eef 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -862,6 +862,18 @@ public final class Bukkit { +@@ -865,6 +865,18 @@ public final class Bukkit { public static World getWorld(@NotNull UUID uid) { return server.getWorld(uid); } @@ -56,10 +56,10 @@ index 27eff0826d5b5b48697fefd9571886e7bbce74b1..d8b1fa79dc24138dc71e32c14bda71c1 // Paper end } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index fd3686688862fccc9989457cf3c1aaff777c66be..1074a858f441133c9c3049601411a00b0d37cf3e 100644 +index 943f8881ea23481ea5d5125b6ec7c9c6f763f0b0..8b52e9a41ea9ba38117d42224811ff28663ef980 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -723,6 +723,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -726,6 +726,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @Nullable public World getWorld(@NotNull UUID uid); @@ -78,10 +78,10 @@ index fd3686688862fccc9989457cf3c1aaff777c66be..1074a858f441133c9c3049601411a00b * Create a new virtual {@link WorldBorder}. *

diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index fb1efc7dfcfbfb823c8ad8fe2943adb99104aefe..1b2b0e6d10393b4f4d0716256aa4c87b57affbe1 100644 +index 460b94538a990a5d136c0c07166887940347c6e2..3c8b0fa78f29b99b9ca092e73732d3001ea66184 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -173,5 +173,10 @@ public interface UnsafeValues { +@@ -177,5 +177,10 @@ public interface UnsafeValues { * Use this when sending custom packets, so that there are no collisions on the client or server. */ public int nextEntityId(); diff --git a/patches/api/0255-Expose-protocol-version.patch b/patches/api/0255-Expose-protocol-version.patch index ac67e3a9220b..b438675f1bac 100644 --- a/patches/api/0255-Expose-protocol-version.patch +++ b/patches/api/0255-Expose-protocol-version.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose protocol version diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 1b2b0e6d10393b4f4d0716256aa4c87b57affbe1..8635846c9f672e39f0929eec7bf83b22536ed284 100644 +index 3c8b0fa78f29b99b9ca092e73732d3001ea66184..538977e150573922d0580521d1a5ea014b0962cd 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -178,5 +178,12 @@ public interface UnsafeValues { +@@ -182,5 +182,12 @@ public interface UnsafeValues { * Just don't use it. */ @org.jetbrains.annotations.NotNull String getMainLevelName(); diff --git a/patches/api/0256-add-isDeeplySleeping-to-HumanEntity.patch b/patches/api/0256-add-isDeeplySleeping-to-HumanEntity.patch index 45207a606474..e561fa1dba96 100644 --- a/patches/api/0256-add-isDeeplySleeping-to-HumanEntity.patch +++ b/patches/api/0256-add-isDeeplySleeping-to-HumanEntity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] add isDeeplySleeping to HumanEntity diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index 083d5798ccc7f37c6df5e234c7ef233202102b8f..a47ea595c2a23b361a56f13877b67892ecfed826 100644 +index 4d6ceca22d98a3e46aa26ef26176c5417a5ccf35..58c842a1fd946d94ae29c7d2439aaf77e47f69b4 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -358,6 +358,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -364,6 +364,15 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder void setHurtDirection(float hurtDirection); // Paper end diff --git a/patches/api/0270-Add-basic-Datapack-API.patch b/patches/api/0270-Add-basic-Datapack-API.patch index f8efe8e60c66..cc389bcd578d 100644 --- a/patches/api/0270-Add-basic-Datapack-API.patch +++ b/patches/api/0270-Add-basic-Datapack-API.patch @@ -70,7 +70,7 @@ index 0000000000000000000000000000000000000000..58f78d5e91beacaf710f62461cf869f7 + +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index a60b1d57904eefeb832ab93fb0e556de9409e5ae..913ab7ce4a754739ef786086d4da55c93d37a39e 100644 +index a2ced20efd2c6be2fe63d80f444c8cb608c37eef..a6e87d06e439bfa85512891da300e2de60b0af95 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -328,9 +328,11 @@ public final class Bukkit { @@ -85,7 +85,7 @@ index a60b1d57904eefeb832ab93fb0e556de9409e5ae..913ab7ce4a754739ef786086d4da55c9 public static DataPackManager getDataPackManager() { return server.getDataPackManager(); } -@@ -2603,6 +2605,14 @@ public final class Bukkit { +@@ -2606,6 +2608,14 @@ public final class Bukkit { public static com.destroystokyo.paper.entity.ai.MobGoals getMobGoals() { return server.getMobGoals(); } @@ -101,7 +101,7 @@ index a60b1d57904eefeb832ab93fb0e556de9409e5ae..913ab7ce4a754739ef786086d4da55c9 @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 1074a858f441133c9c3049601411a00b0d37cf3e..b383ca29be8f86e03e81dbb9962747c03aed1671 100644 +index 8b52e9a41ea9ba38117d42224811ff28663ef980..c3f32db8ccd31e3ee8a544dc165540c0fa8bcc35 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -267,9 +267,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @@ -116,7 +116,7 @@ index 1074a858f441133c9c3049601411a00b0d37cf3e..b383ca29be8f86e03e81dbb9962747c0 public DataPackManager getDataPackManager(); /** -@@ -2270,5 +2272,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2273,5 +2275,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ @NotNull com.destroystokyo.paper.entity.ai.MobGoals getMobGoals(); diff --git a/patches/api/0272-ItemStack-repair-check-API.patch b/patches/api/0272-ItemStack-repair-check-API.patch index 3c15ebede470..95af8264e8d0 100644 --- a/patches/api/0272-ItemStack-repair-check-API.patch +++ b/patches/api/0272-ItemStack-repair-check-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] ItemStack repair check API diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 8635846c9f672e39f0929eec7bf83b22536ed284..51f1a09164d501de6d2561ed90175f2c24a668c1 100644 +index 538977e150573922d0580521d1a5ea014b0962cd..4d9091139b58e3e9208009cd21147a675f98bf64 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -185,5 +185,15 @@ public interface UnsafeValues { +@@ -189,5 +189,15 @@ public interface UnsafeValues { * @return the server's protocol version */ int getProtocolVersion(); diff --git a/patches/api/0304-Get-entity-default-attributes.patch b/patches/api/0304-Get-entity-default-attributes.patch index 3085faf18c16..5ee17cac5f05 100644 --- a/patches/api/0304-Get-entity-default-attributes.patch +++ b/patches/api/0304-Get-entity-default-attributes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Get entity default attributes diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 51f1a09164d501de6d2561ed90175f2c24a668c1..cbc63144e5eb35799548209f8fbee70d0c20a53d 100644 +index 4d9091139b58e3e9208009cd21147a675f98bf64..f74be32f02eeb714e259d58d344306ec089f9063 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -195,5 +195,22 @@ public interface UnsafeValues { +@@ -199,5 +199,22 @@ public interface UnsafeValues { * @return true if valid repair, false if not */ public boolean isValidRepairItemStack(@org.jetbrains.annotations.NotNull ItemStack itemToBeRepaired, @org.jetbrains.annotations.NotNull ItemStack repairMaterial); diff --git a/patches/api/0312-Add-Raw-Byte-Entity-Serialization.patch b/patches/api/0312-Add-Raw-Byte-Entity-Serialization.patch index b90e495870f3..9051505fef74 100644 --- a/patches/api/0312-Add-Raw-Byte-Entity-Serialization.patch +++ b/patches/api/0312-Add-Raw-Byte-Entity-Serialization.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add Raw Byte Entity Serialization diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index cbc63144e5eb35799548209f8fbee70d0c20a53d..240ac3f658ed24d3980707e146e6dfee6c9b31a0 100644 +index f74be32f02eeb714e259d58d344306ec089f9063..528e98a438676fbb6ae0468b8ab8387a6a5c6e7a 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -167,6 +167,14 @@ public interface UnsafeValues { +@@ -171,6 +171,14 @@ public interface UnsafeValues { ItemStack deserializeItem(byte[] data); diff --git a/patches/api/0330-API-for-creating-command-sender-which-forwards-feedb.patch b/patches/api/0330-API-for-creating-command-sender-which-forwards-feedb.patch index bca3814ad84f..d350bacfde84 100644 --- a/patches/api/0330-API-for-creating-command-sender-which-forwards-feedb.patch +++ b/patches/api/0330-API-for-creating-command-sender-which-forwards-feedb.patch @@ -5,10 +5,10 @@ Subject: [PATCH] API for creating command sender which forwards feedback diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 913ab7ce4a754739ef786086d4da55c93d37a39e..69b6c867961d4701a26e8efe048b5bef04c1bcd8 100644 +index a6e87d06e439bfa85512891da300e2de60b0af95..65e02f66fd275045bd1889b460cc6c0613e19755 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1581,6 +1581,20 @@ public final class Bukkit { +@@ -1584,6 +1584,20 @@ public final class Bukkit { return server.getConsoleSender(); } @@ -30,10 +30,10 @@ index 913ab7ce4a754739ef786086d4da55c93d37a39e..69b6c867961d4701a26e8efe048b5bef * Gets the folder that contains all of the various {@link World}s. * diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index b383ca29be8f86e03e81dbb9962747c03aed1671..c79768c995e47470e781645b9e6062b35bb506fd 100644 +index c3f32db8ccd31e3ee8a544dc165540c0fa8bcc35..04b7225486ee61ee66bc8423e46e620c6da9e41d 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1335,6 +1335,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1338,6 +1338,18 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @NotNull public ConsoleCommandSender getConsoleSender(); diff --git a/patches/api/0336-Custom-Potion-Mixes.patch b/patches/api/0336-Custom-Potion-Mixes.patch index 0d3feb9f0945..bafd89bf1f4a 100644 --- a/patches/api/0336-Custom-Potion-Mixes.patch +++ b/patches/api/0336-Custom-Potion-Mixes.patch @@ -155,10 +155,10 @@ index 0000000000000000000000000000000000000000..3ede1e8f7bf0436fdc5bf395c0f9eaf1 + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 69b6c867961d4701a26e8efe048b5bef04c1bcd8..0bb628f1ebfd6eaea23757d928a082afb24a30d1 100644 +index 65e02f66fd275045bd1889b460cc6c0613e19755..702e622a2ef2c3dcb0e582e38b3b10f9c939ed97 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2627,6 +2627,15 @@ public final class Bukkit { +@@ -2630,6 +2630,15 @@ public final class Bukkit { public static io.papermc.paper.datapack.DatapackManager getDatapackManager() { return server.getDatapackManager(); } @@ -175,10 +175,10 @@ index 69b6c867961d4701a26e8efe048b5bef04c1bcd8..0bb628f1ebfd6eaea23757d928a082af @NotNull diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index c79768c995e47470e781645b9e6062b35bb506fd..85fd8980be1f1d878e9be1a823f1ad85fb4427c2 100644 +index 04b7225486ee61ee66bc8423e46e620c6da9e41d..28e883ffb5c4db22613035899be4a627c230fbf4 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2290,5 +2290,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2293,5 +2293,12 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ @NotNull io.papermc.paper.datapack.DatapackManager getDatapackManager(); diff --git a/patches/api/0349-Add-method-isTickingWorlds-to-Bukkit.patch b/patches/api/0349-Add-method-isTickingWorlds-to-Bukkit.patch index 60924390442c..b0d1284d7c4a 100644 --- a/patches/api/0349-Add-method-isTickingWorlds-to-Bukkit.patch +++ b/patches/api/0349-Add-method-isTickingWorlds-to-Bukkit.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add method isTickingWorlds() to Bukkit. diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 0bb628f1ebfd6eaea23757d928a082afb24a30d1..8028a9dd43e161556dcd97aa50648b05ae6ff188 100644 +index 702e622a2ef2c3dcb0e582e38b3b10f9c939ed97..3a8be5316229f372b471549a00eae958543ac91d 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -806,12 +806,26 @@ public final class Bukkit { +@@ -809,12 +809,26 @@ public final class Bukkit { return server.getWorlds(); } @@ -35,7 +35,7 @@ index 0bb628f1ebfd6eaea23757d928a082afb24a30d1..8028a9dd43e161556dcd97aa50648b05 * * @param creator the options to use when creating the world * @return newly created or loaded world -@@ -823,6 +837,9 @@ public final class Bukkit { +@@ -826,6 +840,9 @@ public final class Bukkit { /** * Unloads a world with the given name. @@ -45,7 +45,7 @@ index 0bb628f1ebfd6eaea23757d928a082afb24a30d1..8028a9dd43e161556dcd97aa50648b05 * * @param name Name of the world to unload * @param save whether to save the chunks before unloading -@@ -834,6 +851,9 @@ public final class Bukkit { +@@ -837,6 +854,9 @@ public final class Bukkit { /** * Unloads the given world. @@ -56,10 +56,10 @@ index 0bb628f1ebfd6eaea23757d928a082afb24a30d1..8028a9dd43e161556dcd97aa50648b05 * @param world the world to unload * @param save whether to save the chunks before unloading diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 85fd8980be1f1d878e9be1a823f1ad85fb4427c2..65620c67da99af7e84357fe91d90878ebe84798b 100644 +index 28e883ffb5c4db22613035899be4a627c230fbf4..547ba309beb6a4d1fdfadb234d671c1475abaae5 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -676,34 +676,55 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -679,34 +679,55 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi @NotNull public List getWorlds(); diff --git a/patches/api/0352-Add-Player-getFishHook.patch b/patches/api/0352-Add-Player-getFishHook.patch index feae3b2e4775..61c4560da502 100644 --- a/patches/api/0352-Add-Player-getFishHook.patch +++ b/patches/api/0352-Add-Player-getFishHook.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add Player#getFishHook diff --git a/src/main/java/org/bukkit/entity/HumanEntity.java b/src/main/java/org/bukkit/entity/HumanEntity.java -index a47ea595c2a23b361a56f13877b67892ecfed826..ee866f3497ed56708d4062685f5585ca06a03955 100644 +index 58c842a1fd946d94ae29c7d2439aaf77e47f69b4..294de2c073167e7186fbf1d6885fe5951351cc9c 100644 --- a/src/main/java/org/bukkit/entity/HumanEntity.java +++ b/src/main/java/org/bukkit/entity/HumanEntity.java -@@ -386,6 +386,13 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder +@@ -392,6 +392,13 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder @Nullable public Location getPotentialBedLocation(); // Paper end diff --git a/patches/api/0358-Add-NamespacedKey-biome-methods.patch b/patches/api/0358-Add-NamespacedKey-biome-methods.patch index 29bd350af8b3..905732a22d63 100644 --- a/patches/api/0358-Add-NamespacedKey-biome-methods.patch +++ b/patches/api/0358-Add-NamespacedKey-biome-methods.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add NamespacedKey biome methods Co-authored-by: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 240ac3f658ed24d3980707e146e6dfee6c9b31a0..dad90b98413b57a878f940b8f423bd77e36fd179 100644 +index 528e98a438676fbb6ae0468b8ab8387a6a5c6e7a..7e2a88fc1c73e3991100530d4a45872ba9f90843 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -221,4 +221,33 @@ public interface UnsafeValues { +@@ -225,4 +225,33 @@ public interface UnsafeValues { */ @org.jetbrains.annotations.NotNull org.bukkit.attribute.Attributable getDefaultEntityAttributes(@org.jetbrains.annotations.NotNull NamespacedKey entityKey); // Paper end diff --git a/patches/api/0398-Folia-scheduler-and-owned-region-API.patch b/patches/api/0398-Folia-scheduler-and-owned-region-API.patch index 35af43df05e0..926b2aaea789 100644 --- a/patches/api/0398-Folia-scheduler-and-owned-region-API.patch +++ b/patches/api/0398-Folia-scheduler-and-owned-region-API.patch @@ -499,10 +499,10 @@ index 0000000000000000000000000000000000000000..a6b50c9d8af589cc4747e14d343d2045 + } +} diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 8028a9dd43e161556dcd97aa50648b05ae6ff188..53e86d17867e5c2eae2db6a10bfbed788019a1ad 100644 +index 3a8be5316229f372b471549a00eae958543ac91d..51eaeb14c87e317c37fb6d4082d82542b4b925ee 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2658,6 +2658,141 @@ public final class Bukkit { +@@ -2661,6 +2661,141 @@ public final class Bukkit { } // Paper end @@ -645,10 +645,10 @@ index 8028a9dd43e161556dcd97aa50648b05ae6ff188..53e86d17867e5c2eae2db6a10bfbed78 public static Server.Spigot spigot() { return server.spigot(); diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 65620c67da99af7e84357fe91d90878ebe84798b..e9773ebcc76fb637ed19dce203ae0dfe226b0066 100644 +index 547ba309beb6a4d1fdfadb234d671c1475abaae5..9354a0bb002ddfaf8df90a963ae5be577efb8aee 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -2319,4 +2319,119 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -2322,4 +2322,119 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ @NotNull org.bukkit.potion.PotionBrewer getPotionBrewer(); // Paper end diff --git a/patches/api/0403-API-for-updating-recipes-on-clients.patch b/patches/api/0403-API-for-updating-recipes-on-clients.patch index a3b3f4bb599e..f9ef1b00a029 100644 --- a/patches/api/0403-API-for-updating-recipes-on-clients.patch +++ b/patches/api/0403-API-for-updating-recipes-on-clients.patch @@ -5,10 +5,10 @@ Subject: [PATCH] API for updating recipes on clients diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 53e86d17867e5c2eae2db6a10bfbed788019a1ad..89b797c3468f401a208ef2351ba9f91b234455fd 100644 +index 51eaeb14c87e317c37fb6d4082d82542b4b925ee..c9046e30ae9ffe90a1835316e87988ccca25fb4d 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -990,6 +990,26 @@ public final class Bukkit { +@@ -993,6 +993,26 @@ public final class Bukkit { server.reloadData(); } @@ -35,7 +35,7 @@ index 53e86d17867e5c2eae2db6a10bfbed788019a1ad..89b797c3468f401a208ef2351ba9f91b /** * Returns the primary logger associated with this server instance. * -@@ -1050,6 +1070,20 @@ public final class Bukkit { +@@ -1053,6 +1073,20 @@ public final class Bukkit { return server.addRecipe(recipe); } @@ -56,7 +56,7 @@ index 53e86d17867e5c2eae2db6a10bfbed788019a1ad..89b797c3468f401a208ef2351ba9f91b /** * Get a list of all recipes for a given item. The stack size is ignored * in comparisons. If the durability is -1, it will match any data value. -@@ -1241,6 +1275,24 @@ public final class Bukkit { +@@ -1244,6 +1278,24 @@ public final class Bukkit { return server.removeRecipe(key); } @@ -82,10 +82,10 @@ index 53e86d17867e5c2eae2db6a10bfbed788019a1ad..89b797c3468f401a208ef2351ba9f91b * Gets a list of command aliases defined in the server properties. * diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index e9773ebcc76fb637ed19dce203ae0dfe226b0066..f834dd696d3a40af72ab03f4bd03a784ff5ef23e 100644 +index 9354a0bb002ddfaf8df90a963ae5be577efb8aee..e07fa603227dd936146d1bb810559df527aee0c1 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -839,6 +839,22 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -842,6 +842,22 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ public void reloadData(); @@ -108,7 +108,7 @@ index e9773ebcc76fb637ed19dce203ae0dfe226b0066..f834dd696d3a40af72ab03f4bd03a784 /** * Returns the primary logger associated with this server instance. * -@@ -880,15 +896,34 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -883,15 +899,34 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi public boolean dispatchCommand(@NotNull CommandSender sender, @NotNull String commandLine) throws CommandException; /** @@ -144,7 +144,7 @@ index e9773ebcc76fb637ed19dce203ae0dfe226b0066..f834dd696d3a40af72ab03f4bd03a784 /** * Get a list of all recipes for a given item. The stack size is ignored * in comparisons. If the durability is -1, it will match any data value. -@@ -1057,6 +1092,22 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1060,6 +1095,22 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi */ public boolean removeRecipe(@NotNull NamespacedKey key); diff --git a/patches/api/0405-Fix-custom-statistic-criteria-creation.patch b/patches/api/0405-Fix-custom-statistic-criteria-creation.patch index f4070d7bb410..db402e849190 100644 --- a/patches/api/0405-Fix-custom-statistic-criteria-creation.patch +++ b/patches/api/0405-Fix-custom-statistic-criteria-creation.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix custom statistic criteria creation diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index dad90b98413b57a878f940b8f423bd77e36fd179..f261bd5971003e542e4806c1a989add8e0143466 100644 +index 7e2a88fc1c73e3991100530d4a45872ba9f90843..960afe1bd12296797dca98bbfc66a54c5f1331d1 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -250,4 +250,6 @@ public interface UnsafeValues { +@@ -254,4 +254,6 @@ public interface UnsafeValues { */ void setBiomeKey(RegionAccessor accessor, int x, int y, int z, NamespacedKey biomeKey); // Paper end - namespaced key biome methods diff --git a/patches/api/0408-Deprecate-and-replace-methods-with-old-StructureType.patch b/patches/api/0408-Deprecate-and-replace-methods-with-old-StructureType.patch index b1f1fc1cfcbc..a46b2f61034a 100644 --- a/patches/api/0408-Deprecate-and-replace-methods-with-old-StructureType.patch +++ b/patches/api/0408-Deprecate-and-replace-methods-with-old-StructureType.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Deprecate and replace methods with old StructureType diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 89b797c3468f401a208ef2351ba9f91b234455fd..50d6784c488041ce416845373efebce14321b1ec 100644 +index c9046e30ae9ffe90a1835316e87988ccca25fb4d..fffd4b72672d2e3f82c6a018dfc7e95b6eb3fc2d 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -935,9 +935,6 @@ public final class Bukkit { +@@ -938,9 +938,6 @@ public final class Bukkit { /** * Create a new explorer map targeting the closest nearby structure of a * given {@link StructureType}. @@ -18,7 +18,7 @@ index 89b797c3468f401a208ef2351ba9f91b234455fd..50d6784c488041ce416845373efebce1 * * @param world the world the map will belong to * @param location the origin location to find the nearest structure -@@ -946,7 +943,9 @@ public final class Bukkit { +@@ -949,7 +946,9 @@ public final class Bukkit { * * @see World#locateNearestStructure(org.bukkit.Location, * org.bukkit.StructureType, int, boolean) @@ -28,7 +28,7 @@ index 89b797c3468f401a208ef2351ba9f91b234455fd..50d6784c488041ce416845373efebce1 @NotNull public static ItemStack createExplorerMap(@NotNull World world, @NotNull Location location, @NotNull StructureType structureType) { return server.createExplorerMap(world, location, structureType); -@@ -969,11 +968,54 @@ public final class Bukkit { +@@ -972,11 +971,54 @@ public final class Bukkit { * * @see World#locateNearestStructure(org.bukkit.Location, * org.bukkit.StructureType, int, boolean) @@ -84,10 +84,10 @@ index 89b797c3468f401a208ef2351ba9f91b234455fd..50d6784c488041ce416845373efebce1 /** * Reloads the server, refreshing settings and plugin information. diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index f834dd696d3a40af72ab03f4bd03a784ff5ef23e..23af0b4fa239de8926a36346f38224a00f85284e 100644 +index e07fa603227dd936146d1bb810559df527aee0c1..6d36734580eb411b00757a1cf63a4e05acbae6b2 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -803,16 +803,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -806,16 +806,15 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * * @see World#locateNearestStructure(org.bukkit.Location, * org.bukkit.StructureType, int, boolean) @@ -106,7 +106,7 @@ index f834dd696d3a40af72ab03f4bd03a784ff5ef23e..23af0b4fa239de8926a36346f38224a0 * * @param world the world the map will belong to * @param location the origin location to find the nearest structure -@@ -824,9 +823,50 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -827,9 +826,50 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * * @see World#locateNearestStructure(org.bukkit.Location, * org.bukkit.StructureType, int, boolean) diff --git a/patches/api/0431-Experimental-annotations-change.patch b/patches/api/0431-Experimental-annotations-change.patch index cb37c23bb92a..5144abda5fcf 100644 --- a/patches/api/0431-Experimental-annotations-change.patch +++ b/patches/api/0431-Experimental-annotations-change.patch @@ -69,16 +69,17 @@ index 8d2dd78fc588a6817dfede8040b9909a7d5bde67..f737a2aae3f57a1bfe4cf68ea66f603d /** diff --git a/src/main/java/org/bukkit/block/TrialSpawner.java b/src/main/java/org/bukkit/block/TrialSpawner.java -index 901fea45682ee6be3de3986322509d39f65c7bf6..1c1a91658892941f54934037319ca8f93d764198 100644 +index 2d46d85aff243e9b3c6764f0de041fff6b766853..6fc7b5fe1152f739663a4715a1c93246c3ee6df2 100644 --- a/src/main/java/org/bukkit/block/TrialSpawner.java +++ b/src/main/java/org/bukkit/block/TrialSpawner.java -@@ -5,6 +5,5 @@ import org.jetbrains.annotations.ApiStatus; +@@ -10,7 +10,6 @@ import org.jetbrains.annotations.NotNull; /** * Represents a captured state of a trial spawner. */ -@ApiStatus.Experimental public interface TrialSpawner extends TileState { - } + + /** diff --git a/src/main/java/org/bukkit/block/Vault.java b/src/main/java/org/bukkit/block/Vault.java index f0c5d27f6f1ff56ffe4b88dfdce8d0b7f06d19e1..375f41fe4aebdbf140497b5ba1e54e1c72f0cdfc 100644 --- a/src/main/java/org/bukkit/block/Vault.java diff --git a/patches/api/0443-Add-api-for-spawn-egg-texture-colors.patch b/patches/api/0443-Add-api-for-spawn-egg-texture-colors.patch index 23541c0b38a2..eaeff9f03727 100644 --- a/patches/api/0443-Add-api-for-spawn-egg-texture-colors.patch +++ b/patches/api/0443-Add-api-for-spawn-egg-texture-colors.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add api for spawn egg texture colors diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index f261bd5971003e542e4806c1a989add8e0143466..02d34db5f44ed63c4635077eb2b3cb98ac94b7b2 100644 +index 960afe1bd12296797dca98bbfc66a54c5f1331d1..1887cc2882ea197481b39693cc48aa16ccde5782 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -252,4 +252,17 @@ public interface UnsafeValues { +@@ -256,4 +256,17 @@ public interface UnsafeValues { // Paper end - namespaced key biome methods String getStatisticCriteriaKey(@NotNull org.bukkit.Statistic statistic); // Paper - fix custom stats criteria creation diff --git a/patches/api/0444-Add-Lifecycle-Event-system.patch b/patches/api/0444-Add-Lifecycle-Event-system.patch index d4b3f0411e8d..b1b11e6033d1 100644 --- a/patches/api/0444-Add-Lifecycle-Event-system.patch +++ b/patches/api/0444-Add-Lifecycle-Event-system.patch @@ -528,10 +528,10 @@ index 0000000000000000000000000000000000000000..304f978e40e1759bb19704cc5cec3995 + } +} diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 02d34db5f44ed63c4635077eb2b3cb98ac94b7b2..3f1b48fd65df954e874e6dc6b9093cb12370e2c5 100644 +index 1887cc2882ea197481b39693cc48aa16ccde5782..c8c966feade4881f7a741ce059803f089e96107c 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -265,4 +265,12 @@ public interface UnsafeValues { +@@ -269,4 +269,12 @@ public interface UnsafeValues { */ @Nullable org.bukkit.Color getSpawnEggLayerColor(org.bukkit.entity.EntityType entityType, int layer); // Paper end - spawn egg color visibility diff --git a/patches/api/0445-ItemStack-Tooltip-API.patch b/patches/api/0445-ItemStack-Tooltip-API.patch index 9ed3f18811a4..dccbe82eebad 100644 --- a/patches/api/0445-ItemStack-Tooltip-API.patch +++ b/patches/api/0445-ItemStack-Tooltip-API.patch @@ -108,10 +108,10 @@ index 0000000000000000000000000000000000000000..1d9bed6691f581529c53b577b26f1d0f + } +} diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 3f1b48fd65df954e874e6dc6b9093cb12370e2c5..0e9ccfee7a03d341e7c4d271f53b4ed168b404ef 100644 +index c8c966feade4881f7a741ce059803f089e96107c..8534478dba8b9bdcb9cd1535fb0be18f8638f8b1 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -273,4 +273,6 @@ public interface UnsafeValues { +@@ -277,4 +277,6 @@ public interface UnsafeValues { @org.jetbrains.annotations.ApiStatus.Internal io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager createPluginLifecycleEventManager(final org.bukkit.plugin.java.JavaPlugin plugin, final java.util.function.BooleanSupplier registrationCheck); // Paper end - lifecycle event API diff --git a/patches/api/0449-improve-BanList-types.patch b/patches/api/0449-improve-BanList-types.patch index f392d209dec8..0884753c8631 100644 --- a/patches/api/0449-improve-BanList-types.patch +++ b/patches/api/0449-improve-BanList-types.patch @@ -68,10 +68,10 @@ index a77c0411a68a9bad33ddfb335b7a996a843e478c..739d9d3ec789e58c10c8d818a9ca59ce /** * Banned player names diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index 50d6784c488041ce416845373efebce14321b1ec..b9b751ea0d11381e846d5f35f39f285c075c171a 100644 +index fffd4b72672d2e3f82c6a018dfc7e95b6eb3fc2d..4705c1d91e39fcc3c608b1f1a38a30d063ccf06e 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java -@@ -1649,11 +1649,27 @@ public final class Bukkit { +@@ -1652,11 +1652,27 @@ public final class Bukkit { * @param The ban target * * @return a ban list of the specified type @@ -100,10 +100,10 @@ index 50d6784c488041ce416845373efebce14321b1ec..b9b751ea0d11381e846d5f35f39f285c /** * Gets a set containing all player operators. diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 23af0b4fa239de8926a36346f38224a00f85284e..bbc4d7d3ca84642828f9a3f788ca26bba900d15b 100644 +index 6d36734580eb411b00757a1cf63a4e05acbae6b2..c043d239c449bf4bb13a24467f2f6c67b4d28d2d 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java -@@ -1411,10 +1411,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi +@@ -1414,10 +1414,25 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi * @param The ban target * * @return a ban list of the specified type diff --git a/patches/api/0470-Fix-issues-with-recipe-API.patch b/patches/api/0470-Fix-issues-with-recipe-API.patch index 19c045290e2e..2635c201c974 100644 --- a/patches/api/0470-Fix-issues-with-recipe-API.patch +++ b/patches/api/0470-Fix-issues-with-recipe-API.patch @@ -211,11 +211,11 @@ index 91bfeffcdbe47208c7d0ddbe013cd0f11fddfa32..e7796054f3f65f5bea7f93c75320195f } } diff --git a/src/main/java/org/bukkit/inventory/ShapedRecipe.java b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -index da878c6d4928ddbc16b50ace86d992685a2b7873..28e8d4e4f354b304f32cd8f14dcff7166a7bb37e 100644 +index aa3b3070126f1c492f004ec7599eeb379b58f207..1815de38654dd134abde3dd9bd0b018b91247bd5 100644 --- a/src/main/java/org/bukkit/inventory/ShapedRecipe.java +++ b/src/main/java/org/bukkit/inventory/ShapedRecipe.java -@@ -166,14 +166,15 @@ public class ShapedRecipe extends CraftingRecipe { - public ShapedRecipe setIngredient(char key, @NotNull RecipeChoice ingredient) { +@@ -177,14 +177,15 @@ public class ShapedRecipe extends CraftingRecipe { + Preconditions.checkArgument(key != ' ', "Space in recipe shape must represent no ingredient"); Preconditions.checkArgument(ingredients.containsKey(key), "Symbol does not appear in the shape:", key); - ingredients.put(key, ingredient); diff --git a/patches/api/0476-Registry-Modification-API.patch b/patches/api/0476-Registry-Modification-API.patch index f566c2d39db1..9ad8ef719b36 100644 --- a/patches/api/0476-Registry-Modification-API.patch +++ b/patches/api/0476-Registry-Modification-API.patch @@ -881,10 +881,10 @@ index 27b987db385a594fede4e884b6437dc363f6e817..9725580b6458e5d37fbc6059869604f9 } } diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 0e9ccfee7a03d341e7c4d271f53b4ed168b404ef..7332034bb1753f48f7904dafab1ef4b3ee117ea3 100644 +index 8534478dba8b9bdcb9cd1535fb0be18f8638f8b1..732f4f2eafd5c8bf676c963c689cfd0f7e1c1502 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -275,4 +275,6 @@ public interface UnsafeValues { +@@ -279,4 +279,6 @@ public interface UnsafeValues { // Paper end - lifecycle event API @NotNull java.util.List computeTooltipLines(@NotNull ItemStack itemStack, @NotNull io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, @Nullable org.bukkit.entity.Player player); // Paper - expose itemstack tooltip lines diff --git a/patches/api/0478-Proxy-ItemStack-to-CraftItemStack.patch b/patches/api/0478-Proxy-ItemStack-to-CraftItemStack.patch index 9a283e022c2d..c974d8f39779 100644 --- a/patches/api/0478-Proxy-ItemStack-to-CraftItemStack.patch +++ b/patches/api/0478-Proxy-ItemStack-to-CraftItemStack.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Proxy ItemStack to CraftItemStack diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 7332034bb1753f48f7904dafab1ef4b3ee117ea3..11bccf6c27b8b2a2ed558a1375a3b3adc7952076 100644 +index 732f4f2eafd5c8bf676c963c689cfd0f7e1c1502..c133564b8e8364f1eb7f0e82eed3b0add7f47351 100644 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -277,4 +277,6 @@ public interface UnsafeValues { +@@ -281,4 +281,6 @@ public interface UnsafeValues { @NotNull java.util.List computeTooltipLines(@NotNull ItemStack itemStack, @NotNull io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, @Nullable org.bukkit.entity.Player player); // Paper - expose itemstack tooltip lines io.papermc.paper.registry.tag.@Nullable Tag getTag(io.papermc.paper.registry.tag.@NotNull TagKey tagKey); // Paper - hack to get tags for non-server backed registries diff --git a/patches/server/0003-Build-system-changes.patch b/patches/server/0003-Build-system-changes.patch index 364223048132..0961be72a45e 100644 --- a/patches/server/0003-Build-system-changes.patch +++ b/patches/server/0003-Build-system-changes.patch @@ -131,7 +131,7 @@ index feca36209fd2405fab70f564f63e627b8b78ac18..396ec10a76bdadbf5be2f0e15e88eed4 public static PackRepository createPackRepository(Path dataPacksPath, DirectoryValidator symlinkFinder) { diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 5595eb892fa868508c45448942da65d7c11d49fd..4b8602b168f9dd386aa72b4e5d189c441c93542e 100644 +index 9c232b6eb11d87420fb24a668a2043581cca3bd2..5f73afa688fd1c83af17e6f566862cd5e2603ff3 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -210,7 +210,7 @@ public class Main { @@ -142,7 +142,7 @@ index 5595eb892fa868508c45448942da65d7c11d49fd..4b8602b168f9dd386aa72b4e5d189c44 + Date buildDate = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(Main.class.getPackage().getImplementationVendor()); // Paper Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -3); + deadline.add(Calendar.DAY_OF_YEAR, -7); diff --git a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java b/src/main/java/org/bukkit/craftbukkit/util/Versioning.java index 93046379d0cefd5d3236fc59e698809acdc18f80..774556a62eb240da42e84db4502e2ed43495be17 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Versioning.java diff --git a/patches/server/0008-CB-fixes.patch b/patches/server/0008-CB-fixes.patch index 1062e3ebb7e5..178007d7bd32 100644 --- a/patches/server/0008-CB-fixes.patch +++ b/patches/server/0008-CB-fixes.patch @@ -102,7 +102,7 @@ index f1302dfb68bf8e4e1f4d8b084ad81422f65eecc4..fe0f57dbeecc4b5a0c81863f33e41d11 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 1e3ca7ca98abfd5be233a7eeb6dad201776d2d6a..9ec50bbb262b25fea157ae48e8395f5cd38f8906 100644 +index e2bfbedce18c4ecb01ffcc44d495e72b76806a92..7e3c4c8a4d87e0c616a9fb98f09d89c93597bb23 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -123,6 +123,7 @@ public class Main { @@ -134,10 +134,10 @@ index 905adf97c0d1f0d1c774a6835a5dffcfea884e58..c017ce2ca1bc535795c958a2e509af2a public class CraftScheduler implements BukkitScheduler { diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 4c3c9c0e01ba8eeb9bd3f31cd795445cf03f8278..e08d4a45e313ef1b9005ef00ee0185a188171207 100644 +index cfb4cf66aa5f32a96a15886c6cf4a3946bd232ec..aa6a9dcd5528df38dddc0c661334c35658a19cee 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -244,7 +244,7 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -240,7 +240,7 @@ public final class CraftMagicNumbers implements UnsafeValues { try { nmsStack.applyComponents(new ItemParser(Commands.createValidationContext(MinecraftServer.getDefaultRegistryAccess())).parse(new StringReader(arguments)).components()); } catch (CommandSyntaxException ex) { diff --git a/patches/server/0009-MC-Utils.patch b/patches/server/0009-MC-Utils.patch index c12a8e7c5c85..653f48c15747 100644 --- a/patches/server/0009-MC-Utils.patch +++ b/patches/server/0009-MC-Utils.patch @@ -4864,7 +4864,7 @@ index 9d11fcb3df12182ae00ce73f7e30091fd199a341..eea8bafd98e3a8d82b3216488537ab89 public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { // IRegistryCustom.Dimension iregistrycustom_dimension = minecraftserver.registryAccess(); // CraftBukkit - decompile error diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index f6e28e64024549f4562ec4a4ba46a0429d9a9d52..d02e958d74fe4bb97ce36ca04a36bcf7e73de016 100644 +index defe0b30964613cbae5195485aafff21d73ff18e..684dfbcdd4d000ac918c0f77a60c9abf9b30d3a4 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -280,6 +280,8 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @@ -4975,7 +4975,7 @@ index 586acbb52b0fcb09cda195b49b6c737a29a4e35e..b0843917caedc32f800c50cc54706ace public Entity(EntityType type, Level world) { this.id = Entity.ENTITY_COUNTER.incrementAndGet(); diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 726354da4a0008c0f09a0ac8a668378c75ee99b0..2345d79ebf1562054cb071ff1786392a937c8243 100644 +index 12db4c5db3d7951df984db03d09d14d808e58699..44d4aee059d74676bffb8b6bc6f6ad4dd96fcb33 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -282,6 +282,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -5634,10 +5634,10 @@ index 508419378c88ba8688edbd5142d9d8ba52396507..a59eebb89d11788b999d1e5cb4fd2f4e + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 91539582b65a87e2ed9901f2837c3148455d2669..c025542b1073ce7e6e30a43744276fd1fa1ca484 100644 +index e130d0aa64d0caaa7760d8de4b1f989523f9de20..45108559bb2e4ae9d33aed5d92b72cbe5c17f553 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2419,4 +2419,34 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2420,4 +2420,34 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this.spigot; } // Spigot end @@ -5920,10 +5920,10 @@ index 0000000000000000000000000000000000000000..909b2c98e7a9117d2f737245e4661792 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index e08d4a45e313ef1b9005ef00ee0185a188171207..2fc68d129e2fdfd51e310ea5bdfb83322666c87b 100644 +index aa6a9dcd5528df38dddc0c661334c35658a19cee..65b92a787b131984ad3e48d8dd6812e1b433c77f 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -110,8 +110,17 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -106,8 +106,17 @@ public final class CraftMagicNumbers implements UnsafeValues { private static final Map ITEM_MATERIAL = new HashMap<>(); private static final Map MATERIAL_ITEM = new HashMap<>(); private static final Map MATERIAL_BLOCK = new HashMap<>(); @@ -5941,7 +5941,7 @@ index e08d4a45e313ef1b9005ef00ee0185a188171207..2fc68d129e2fdfd51e310ea5bdfb8332 for (Block block : BuiltInRegistries.BLOCK) { BLOCK_MATERIAL.put(block, Material.getMaterial(BuiltInRegistries.BLOCK.getKey(block).getPath().toUpperCase(Locale.ROOT))); } -@@ -162,6 +171,14 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -158,6 +167,14 @@ public final class CraftMagicNumbers implements UnsafeValues { public static ResourceLocation key(Material mat) { return CraftNamespacedKey.toMinecraft(mat.getKey()); } diff --git a/patches/server/0010-Adventure.patch b/patches/server/0010-Adventure.patch index 9d84d97b3c73..fff8643fbdcf 100644 --- a/patches/server/0010-Adventure.patch +++ b/patches/server/0010-Adventure.patch @@ -2699,7 +2699,7 @@ index 9eb987f9d86396d6b7e9d4f3834bea3326640ac7..25d6be308be03815301cfbefdc4199c8 public boolean logIPs() { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index d02e958d74fe4bb97ce36ca04a36bcf7e73de016..dc92e1cd0a10ec4e6b4ad6145d5fc0a4ef199365 100644 +index 684dfbcdd4d000ac918c0f77a60c9abf9b30d3a4..200993e8c482442a2c7ae4d9551d04708178bb24 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -171,6 +171,7 @@ import net.minecraft.world.item.trading.MerchantOffers; @@ -2974,7 +2974,7 @@ index 8e715261b99bcc19b6f4b9787987c59aa19ba70e..851e4bdf1739736fd193786a6541ffb3 } } diff --git a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java -index 2c555c5ad05992b19f67b883c3c0ec7018180747..71540687b4212702cdaaad5fd4815fb3eb97ddd6 100644 +index 3848cc836785829c5aa82bdb5d37d36a97f94a04..f08700abb005f487aca95c0457c09cefa9a81be2 100644 --- a/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerStatusPacketListenerImpl.java @@ -58,7 +58,7 @@ public class ServerStatusPacketListenerImpl implements ServerStatusPacketListene @@ -3627,7 +3627,7 @@ index a59eebb89d11788b999d1e5cb4fd2f4e55e023ab..1e8d93d81b7a391bbd1e9926ff35a68d // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 9ec50bbb262b25fea157ae48e8395f5cd38f8906..985b77911d03bc60a0210b796e901f31e2676268 100644 +index 7e3c4c8a4d87e0c616a9fb98f09d89c93597bb23..0736cf0b5ea327e73a457b55c9c0c4bb82d4c6e9 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -20,6 +20,12 @@ public class Main { @@ -4015,10 +4015,10 @@ index 1e82312c24cb752d63b165926861fc178cd7849b..7f22950ae61436e91a59cd29a345809c + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index ed6944418382dbd02e5ddbf50c6ac4bb26415807..97a7dc31fe7a2defed2202ccc518c66b7ff4b0da 100644 +index 2d0c82ca240e371a756d71f28e2e04d1aa8e6ad2..f73017bff613bd62b86c974b29576e241c24c927 100644 --- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -166,6 +166,12 @@ public class CraftEnchantment extends Enchantment implements Handleable windowType = CraftContainer.getNotchInventoryType(inventory.getTopInventory()); @@ -4147,7 +4147,7 @@ index 55945b83a5426b352bad9507cc9e94afb1278032..9ea1537408ff2d790747b6e5a681d917 public boolean isOp() { return true; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c025542b1073ce7e6e30a43744276fd1fa1ca484..03c70d45941822239a0894f910cbaf114b939bec 100644 +index 45108559bb2e4ae9d33aed5d92b72cbe5c17f553..859f3eb2d616156b0efaa70ee03e357e6f0760f3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -388,14 +388,40 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -4252,7 +4252,7 @@ index c025542b1073ce7e6e30a43744276fd1fa1ca484..03c70d45941822239a0894f910cbaf11 } @@ -481,6 +508,23 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - this.getHandle().connection.disconnect(CraftChatMessage.fromStringOrEmpty(message)); + this.getHandle().connection.disconnect(CraftChatMessage.fromStringOrEmpty(message, true)); } + // Paper start @@ -4313,7 +4313,7 @@ index c025542b1073ce7e6e30a43744276fd1fa1ca484..03c70d45941822239a0894f910cbaf11 SignBlockEntity sign = new SignBlockEntity(CraftLocation.toBlockPosition(loc), Blocks.OAK_SIGN.defaultBlockState()); SignText text = sign.getFrontText(); text = text.setColor(net.minecraft.world.item.DyeColor.byId(dyeColor.getWoolData())); -@@ -1815,7 +1883,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1816,7 +1884,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setResourcePack(String url) { @@ -4322,7 +4322,7 @@ index c025542b1073ce7e6e30a43744276fd1fa1ca484..03c70d45941822239a0894f910cbaf11 } @Override -@@ -1830,7 +1898,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1831,7 +1899,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setResourcePack(String url, byte[] hash, boolean force) { @@ -4331,7 +4331,7 @@ index c025542b1073ce7e6e30a43744276fd1fa1ca484..03c70d45941822239a0894f910cbaf11 } @Override -@@ -1867,6 +1935,59 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1868,6 +1936,59 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.handlePushResourcePack(new ClientboundResourcePackPushPacket(id, url, hashStr, force, CraftChatMessage.fromStringOrOptional(prompt, true)), false); } @@ -4391,7 +4391,7 @@ index c025542b1073ce7e6e30a43744276fd1fa1ca484..03c70d45941822239a0894f910cbaf11 @Override public void removeResourcePack(UUID id) { Preconditions.checkArgument(id != null, "Resource pack id cannot be null"); -@@ -2287,6 +2408,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2288,6 +2409,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return (this.getHandle().requestedViewDistance() == 0) ? Bukkit.getViewDistance() : this.getHandle().requestedViewDistance(); } @@ -4404,7 +4404,7 @@ index c025542b1073ce7e6e30a43744276fd1fa1ca484..03c70d45941822239a0894f910cbaf11 @Override public int getPing() { return this.getHandle().connection.latency(); -@@ -2337,6 +2464,248 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2338,6 +2465,248 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this.getHandle().allowsListing(); } @@ -4676,10 +4676,10 @@ index 5725b0281ac53a2354b233223259d6784353bc6e..9ef939b76d06874b856e0c850addb364 @Override public int getLineWidth() { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 889af27e3fe5ce98b68b3177639c338ca287b024..a29dfbe7aa06113358a2078d927fc53662a5f91f 100644 +index ae357fc3cabd9235488665ef74a3f7c703d64980..3595ff3db5eb0b1da100692702e514cb870220ee 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -907,7 +907,7 @@ public class CraftEventFactory { +@@ -908,7 +908,7 @@ public class CraftEventFactory { return event; } @@ -4886,7 +4886,7 @@ index 9e05a8515c5f6f340182e91150fcad8bbf80a22b..adf22ce4f0bcd3bd57dc2030c6c92d3d @Override public CraftMerchant getCraftMerchant() { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 61ad00c38cfef8a1de61b4597ec1042428feccf4..4da38ebb7fdbdb0f8fa422ebcd2e3eec2b2be846 100644 +index 3ab6b212001c2b92cac42c0ff97e59c3d08b3e49..552ebe67f87b48734adf0da8ef78dcac9dd670a2 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java @@ -2,8 +2,9 @@ package org.bukkit.craftbukkit.inventory; @@ -5041,24 +5041,15 @@ index 61ad00c38cfef8a1de61b4597ec1042428feccf4..4da38ebb7fdbdb0f8fa422ebcd2e3eec if (this.pages != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -index 2e6f0a0f4bbe4ae3c7c85e679f6187e89d1298ff..c7360e2b2d6e50abc371c21b09cdadd63892f439 100644 +index c71a4971f127fdfc753306019313ce1a31201120..162997fc80dfe2df1f13c802c1b610f04cb9d05a 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -@@ -2,7 +2,7 @@ package org.bukkit.craftbukkit.inventory; - - import com.google.common.base.Preconditions; - import com.google.common.collect.ImmutableList; --import com.google.common.collect.ImmutableMap.Builder; -+import com.google.common.collect.ImmutableMap; // Paper - import java.util.ArrayList; - import java.util.Arrays; - import java.util.List; @@ -346,7 +346,7 @@ public class CraftMetaBookSigned extends CraftMetaItem implements BookMeta { } @Override - Builder serialize(Builder builder) { -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { ++ com.google.common.collect.ImmutableMap.Builder serialize(com.google.common.collect.ImmutableMap.Builder builder) { // Paper - adventure - fqn as it conflicts with adventure book builder super.serialize(builder); if (this.hasTitle()) { @@ -5177,7 +5168,7 @@ index 2e6f0a0f4bbe4ae3c7c85e679f6187e89d1298ff..c7360e2b2d6e50abc371c21b09cdadd6 + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 607456854e6bce3f7b58469af4ce42b8bacb72fc..9ecbdd50aa2eb7851ce1716946fa31e5db8765b4 100644 +index e56e6d07f297491c8f92598b8105bfebead7a0a1..86a5e4f7b2a0d50d0a58d88e10a277cfbd09bf9d 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -952,6 +952,18 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { @@ -5589,10 +5580,10 @@ index 4d586e1375ed8782939c9d480479e0dd981f8cbc..7900adb0b158bc17dd792dd082c33854 + } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -index 28038c3a531680201dcc8f2716b8f46f3886e769..5a9ddf71dc186c537a23083ac59434fb446a2140 100644 +index ff040613083c015d9c52c0995591b64305fd5018..1b552b3f05ac7fc44450de4b1ec78907a0f62424 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftChatMessage.java -@@ -308,6 +308,7 @@ public final class CraftChatMessage { +@@ -264,6 +264,7 @@ public final class CraftChatMessage { public static String fromComponent(Component component) { if (component == null) return ""; @@ -5601,10 +5592,10 @@ index 28038c3a531680201dcc8f2716b8f46f3886e769..5a9ddf71dc186c537a23083ac59434fb boolean hadFormat = false; diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 2fc68d129e2fdfd51e310ea5bdfb83322666c87b..fb22e04a4a9f039f0e942ff837124b00ca1b12be 100644 +index 65b92a787b131984ad3e48d8dd6812e1b433c77f..1bf1f10f8691922a69cd13c6a4e643b863801b4f 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -81,6 +81,43 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -77,6 +77,43 @@ public final class CraftMagicNumbers implements UnsafeValues { private CraftMagicNumbers() {} diff --git a/patches/server/0019-Paper-Plugins.patch b/patches/server/0019-Paper-Plugins.patch index 8bb43515e2a1..77003e31d5bc 100644 --- a/patches/server/0019-Paper-Plugins.patch +++ b/patches/server/0019-Paper-Plugins.patch @@ -7346,10 +7346,10 @@ index 909b2c98e7a9117d2f737245e4661792ffafb744..d96399e9bf1a58db5a4a22e58abb99e7 @Override public FileConfiguration getConfig() { diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index fb22e04a4a9f039f0e942ff837124b00ca1b12be..297767f64c1a7c01cffd6d78e71b60746622f22e 100644 +index 1bf1f10f8691922a69cd13c6a4e643b863801b4f..e8205646dbe7088e6bdece2567151bd7f64f36cb 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -426,6 +426,16 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -412,6 +412,16 @@ public final class CraftMagicNumbers implements UnsafeValues { net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack); return nmsItemStack.getItem().getDescriptionId(nmsItemStack); } diff --git a/patches/server/0021-Hook-into-CB-plugin-rewrites.patch b/patches/server/0021-Hook-into-CB-plugin-rewrites.patch index 1bdec9b9e944..26965088ba98 100644 --- a/patches/server/0021-Hook-into-CB-plugin-rewrites.patch +++ b/patches/server/0021-Hook-into-CB-plugin-rewrites.patch @@ -8,7 +8,7 @@ our own relocation. Also lets us rewrite NMS calls for when we're debugging in an IDE pre-relocate. diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -index 3526ece6c12f76eca93c995018e0f262360e1ba9..51452d8a8969a303be1be5851b251243a5944be3 100644 +index acfb0269e15aba638b87b1e2f483ef96c9552693..8e29fae1be2b4d0b04e7788de7a3802aacae4588 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java @@ -8,6 +8,7 @@ import java.util.ArrayList; @@ -68,7 +68,7 @@ index 3526ece6c12f76eca93c995018e0f262360e1ba9..51452d8a8969a303be1be5851b251243 public static void main(String[] args) { OptionParser parser = new OptionParser(); OptionSpec inputFlag = parser.acceptsAll(Arrays.asList("i", "input")).withRequiredArg().ofType(File.class).required(); -@@ -209,9 +245,49 @@ public class Commodore { +@@ -213,9 +249,49 @@ public class Commodore { @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { return new MethodVisitor(this.api, super.visitMethod(access, name, desc, signature, exceptions)) { @@ -118,7 +118,7 @@ index 3526ece6c12f76eca93c995018e0f262360e1ba9..51452d8a8969a303be1be5851b251243 name = FieldRename.rename(pluginVersion, owner, name); if (modern) { -@@ -321,6 +397,13 @@ public class Commodore { +@@ -331,6 +407,13 @@ public class Commodore { return; } @@ -132,7 +132,7 @@ index 3526ece6c12f76eca93c995018e0f262360e1ba9..51452d8a8969a303be1be5851b251243 if (modern) { if (owner.equals("org/bukkit/Material") || (instantiatedMethodType != null && instantiatedMethodType.getDescriptor().startsWith("(Lorg/bukkit/Material;)"))) { switch (name) { -@@ -417,6 +500,13 @@ public class Commodore { +@@ -427,6 +510,13 @@ public class Commodore { @Override public void visitLdcInsn(Object value) { @@ -146,7 +146,7 @@ index 3526ece6c12f76eca93c995018e0f262360e1ba9..51452d8a8969a303be1be5851b251243 if (value instanceof String && ((String) value).equals("com.mysql.jdbc.Driver")) { super.visitLdcInsn("com.mysql.cj.jdbc.Driver"); return; -@@ -427,6 +517,14 @@ public class Commodore { +@@ -437,6 +527,14 @@ public class Commodore { @Override public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) { @@ -161,7 +161,7 @@ index 3526ece6c12f76eca93c995018e0f262360e1ba9..51452d8a8969a303be1be5851b251243 if (bootstrapMethodHandle.getOwner().equals("java/lang/invoke/LambdaMetafactory") && bootstrapMethodHandle.getName().equals("metafactory") && bootstrapMethodArguments.length == 3) { Type samMethodType = (Type) bootstrapMethodArguments[0]; -@@ -443,7 +541,7 @@ public class Commodore { +@@ -453,7 +551,7 @@ public class Commodore { methodArgs.add(new Handle(newOpcode, newOwner, newName, newDescription, newItf)); methodArgs.add(newInstantiated); @@ -170,7 +170,7 @@ index 3526ece6c12f76eca93c995018e0f262360e1ba9..51452d8a8969a303be1be5851b251243 }, implMethod.getTag(), implMethod.getOwner(), implMethod.getName(), implMethod.getDesc(), implMethod.isInterface(), samMethodType, instantiatedMethodType); return; } -@@ -494,6 +592,12 @@ public class Commodore { +@@ -504,6 +602,12 @@ public class Commodore { @Override public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { diff --git a/patches/server/0022-Remap-reflection-calls-in-plugins-using-internals.patch b/patches/server/0022-Remap-reflection-calls-in-plugins-using-internals.patch index 2d1c651eeff0..71679c179f2a 100644 --- a/patches/server/0022-Remap-reflection-calls-in-plugins-using-internals.patch +++ b/patches/server/0022-Remap-reflection-calls-in-plugins-using-internals.patch @@ -645,7 +645,7 @@ index 242811578a786e3807a1a7019d472d5a68f87116..0b65fdf53124f3dd042b2363b1b8df8e return traceElements; } diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -index 51452d8a8969a303be1be5851b251243a5944be3..8757d4de8a589355b83690d37d9e81ce3cc6ae32 100644 +index 8e29fae1be2b4d0b04e7788de7a3802aacae4588..0bde8fc63d892cb615638769ca84beba9da80ff2 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java @@ -86,36 +86,26 @@ public class Commodore { @@ -706,10 +706,10 @@ index 51452d8a8969a303be1be5851b251243a5944be3..8757d4de8a589355b83690d37d9e81ce String className; boolean isInterface; diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 297767f64c1a7c01cffd6d78e71b60746622f22e..d551c9d898d8b5128dfef84d206396c84072abe4 100644 +index e8205646dbe7088e6bdece2567151bd7f64f36cb..10b5fcf6575255000e52166eb73b60f6a3f88e84 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -361,7 +361,7 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -357,7 +357,7 @@ public final class CraftMagicNumbers implements UnsafeValues { throw new InvalidPluginException("Plugin API version " + pdf.getAPIVersion() + " is lower than the minimum allowed version. Please update or replace it."); } @@ -718,7 +718,7 @@ index 297767f64c1a7c01cffd6d78e71b60746622f22e..d551c9d898d8b5128dfef84d206396c8 CraftLegacy.init(); } -@@ -376,6 +376,7 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -372,6 +372,7 @@ public final class CraftMagicNumbers implements UnsafeValues { @Override public byte[] processClass(PluginDescriptionFile pdf, String path, byte[] clazz) { diff --git a/patches/server/0023-Timings-v2.patch b/patches/server/0023-Timings-v2.patch index 3ed1b8f74ebf..5b034492d80f 100644 --- a/patches/server/0023-Timings-v2.patch +++ b/patches/server/0023-Timings-v2.patch @@ -1379,7 +1379,7 @@ index e465aaa4fd29b4966ea8d88316c6d8f217da2e73..474f020371bb9e5fd2c5b22e44d79029 } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 2345d79ebf1562054cb071ff1786392a937c8243..bb5e2fd7b8d9b8bec71d8c945d266765c42d3927 100644 +index 44d4aee059d74676bffb8b6bc6f6ad4dd96fcb33..97ad63aad3c559feb1e762af1e00fd550aa5b251 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -156,7 +156,7 @@ import org.bukkit.event.entity.EntityTeleportEvent; @@ -1391,7 +1391,7 @@ index 2345d79ebf1562054cb071ff1786392a937c8243..bb5e2fd7b8d9b8bec71d8c945d266765 public abstract class LivingEntity extends Entity implements Attackable { -@@ -2949,7 +2949,6 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2977,7 +2977,6 @@ public abstract class LivingEntity extends Entity implements Attackable { @Override public void tick() { @@ -1399,7 +1399,7 @@ index 2345d79ebf1562054cb071ff1786392a937c8243..bb5e2fd7b8d9b8bec71d8c945d266765 super.tick(); this.updatingUsingItem(); this.updateSwimAmount(); -@@ -2991,9 +2990,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3019,9 +3018,7 @@ public abstract class LivingEntity extends Entity implements Attackable { } if (!this.isRemoved()) { @@ -1409,7 +1409,7 @@ index 2345d79ebf1562054cb071ff1786392a937c8243..bb5e2fd7b8d9b8bec71d8c945d266765 } double d0 = this.getX() - this.xo; -@@ -3084,7 +3081,6 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3112,7 +3109,6 @@ public abstract class LivingEntity extends Entity implements Attackable { this.refreshDimensions(); } @@ -1417,7 +1417,7 @@ index 2345d79ebf1562054cb071ff1786392a937c8243..bb5e2fd7b8d9b8bec71d8c945d266765 } public void detectEquipmentUpdatesPublic() { // CraftBukkit -@@ -3300,7 +3296,6 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3328,7 +3324,6 @@ public abstract class LivingEntity extends Entity implements Attackable { this.setDeltaMovement(d0, d1, d2); this.level().getProfiler().push("ai"); @@ -1425,7 +1425,7 @@ index 2345d79ebf1562054cb071ff1786392a937c8243..bb5e2fd7b8d9b8bec71d8c945d266765 if (this.isImmobile()) { this.jumping = false; this.xxa = 0.0F; -@@ -3310,7 +3305,6 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3338,7 +3333,6 @@ public abstract class LivingEntity extends Entity implements Attackable { this.serverAiStep(); this.level().getProfiler().pop(); } @@ -1433,7 +1433,7 @@ index 2345d79ebf1562054cb071ff1786392a937c8243..bb5e2fd7b8d9b8bec71d8c945d266765 this.level().getProfiler().pop(); this.level().getProfiler().push("jump"); -@@ -3350,7 +3344,6 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3378,7 +3372,6 @@ public abstract class LivingEntity extends Entity implements Attackable { this.resetFallDistance(); } @@ -1441,7 +1441,7 @@ index 2345d79ebf1562054cb071ff1786392a937c8243..bb5e2fd7b8d9b8bec71d8c945d266765 label104: { LivingEntity entityliving = this.getControllingPassenger(); -@@ -3364,7 +3357,6 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3392,7 +3385,6 @@ public abstract class LivingEntity extends Entity implements Attackable { this.travel(vec3d1); } @@ -1449,7 +1449,7 @@ index 2345d79ebf1562054cb071ff1786392a937c8243..bb5e2fd7b8d9b8bec71d8c945d266765 this.level().getProfiler().pop(); this.level().getProfiler().push("freezing"); -@@ -3391,9 +3383,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3419,9 +3411,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); } @@ -1805,10 +1805,10 @@ index b0ffa23faf62629043dfd613315eaf9c5fcc2cfe..00000000000000000000000000000000 - } -} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 03c70d45941822239a0894f910cbaf114b939bec..0a4d672adf9684b483964414cc14a58001aca508 100644 +index 859f3eb2d616156b0efaa70ee03e357e6f0760f3..a02e5c967d9dfcd507e1019d28ed3735945f9613 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2781,6 +2781,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2782,6 +2782,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { CraftPlayer.this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSystemChatPacket(components, position == net.md_5.bungee.api.ChatMessageType.ACTION_BAR)); } @@ -2005,10 +2005,10 @@ index f97eccb6a17c7876e1e002d798eb67bbe80571a0..76effc345d362047e64d064eb64a5222 + } // Paper } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index d551c9d898d8b5128dfef84d206396c84072abe4..99f134d03b76e867a3e5084c5c89e53c74d8e7af 100644 +index 10b5fcf6575255000e52166eb73b60f6a3f88e84..a356d4d19e4b7a3d08c80a137609d1ed9db7c1b1 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -217,6 +217,12 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -213,6 +213,12 @@ public final class CraftMagicNumbers implements UnsafeValues { } // Paper end // ======================================================================== @@ -2021,7 +2021,7 @@ index d551c9d898d8b5128dfef84d206396c84072abe4..99f134d03b76e867a3e5084c5c89e53c public static byte toLegacyData(BlockState data) { return CraftLegacy.toLegacyData(data); -@@ -467,6 +473,12 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -453,6 +459,12 @@ public final class CraftMagicNumbers implements UnsafeValues { public DamageSource.Builder createDamageSourceBuilder(DamageType damageType) { return new CraftDamageSourceBuilder(damageType); } diff --git a/patches/server/0034-Expose-server-build-information.patch b/patches/server/0034-Expose-server-build-information.patch index c8902cb0bcab..985fec1d8b80 100644 --- a/patches/server/0034-Expose-server-build-information.patch +++ b/patches/server/0034-Expose-server-build-information.patch @@ -598,7 +598,7 @@ index a2f784b28c0d974ee45d61d6a3a0096dd7161d3e..7c97ec4aa57562a8383a40e493eaa8a3 public List getOnlinePlayers() { return this.playerView; diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index bc664b090e16ed27ba795c204dc5639679e6eee8..9dc72b01092783c436bc1fa8ce29ff7cdaa39b19 100644 +index bd21da04390e486731a260f8fb0c70921320198e..14f63c179428bee61d3b931ea309f4c94b89a6cc 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -15,6 +15,7 @@ import joptsimple.OptionSet; @@ -610,7 +610,7 @@ index bc664b090e16ed27ba795c204dc5639679e6eee8..9dc72b01092783c436bc1fa8ce29ff7c public static boolean useConsole = true; @@ -252,13 +253,26 @@ public class Main { - deadline.add(Calendar.DAY_OF_YEAR, -3); + deadline.add(Calendar.DAY_OF_YEAR, -7); if (buildDate.before(deadline.getTime())) { System.err.println("*** Error, this build is outdated ***"); - System.err.println("*** Please download a new build as per instructions from https://www.spigotmc.org/go/outdated-spigot ***"); @@ -638,10 +638,10 @@ index bc664b090e16ed27ba795c204dc5639679e6eee8..9dc72b01092783c436bc1fa8ce29ff7c net.minecraft.server.Main.main(options); } catch (Throwable t) { diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 99f134d03b76e867a3e5084c5c89e53c74d8e7af..7800e0a5aa381181d6a19d55f90490154de05c04 100644 +index a356d4d19e4b7a3d08c80a137609d1ed9db7c1b1..e85faddc157869824e30426a7ca2c577552aea9c 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -478,6 +478,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -464,6 +464,11 @@ public final class CraftMagicNumbers implements UnsafeValues { public String getTimingsServerName() { return io.papermc.paper.configuration.GlobalConfiguration.get().timings.serverName; } diff --git a/patches/server/0035-Player-affects-spawning-API.patch b/patches/server/0035-Player-affects-spawning-API.patch index 825077ccaba7..2658310aaf56 100644 --- a/patches/server/0035-Player-affects-spawning-API.patch +++ b/patches/server/0035-Player-affects-spawning-API.patch @@ -73,10 +73,10 @@ index 393a9c704f4637a0e8031328d2a0facef4723dd8..d97c3c139f10a45febc0cfb1057ff6e3 entityzombie.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.REINFORCEMENT, (SpawnGroupData) null); worldserver.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index f652859457171759f72800df7a8d5475a0486759..0d1d8ad353ff2f2bd478cfdc2f6bebad5203e190 100644 +index 56f4d85d0d2014dfe4fb2598fa813ffc4a768d25..ba279ab6ec0ab41309607333b62a941e35dbf581 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -194,6 +194,7 @@ public abstract class Player extends LivingEntity { +@@ -195,6 +195,7 @@ public abstract class Player extends LivingEntity { public Entity currentExplosionCause; private boolean ignoreFallDamageFromCurrentImpulse; private int currentImpulseContextResetGraceTime; @@ -135,10 +135,10 @@ index f38f62e777d88a783e1e3b7e1a48da921cc67cf4..77ae7882a08441d9a80b50492be5e484 for (Player player : this.players()) { if (EntitySelector.NO_SPECTATORS.test(player) && EntitySelector.LIVING_ENTITY_STILL_ALIVE.test(player)) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0a4d672adf9684b483964414cc14a58001aca508..96300cb91f734f45ca9bcf8b7a8e727049325144 100644 +index a02e5c967d9dfcd507e1019d28ed3735945f9613..69b4e27c6939f5a20276922714601b02d2832517 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2424,6 +2424,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2425,6 +2425,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this.getHandle().language; } diff --git a/patches/server/0036-Only-refresh-abilities-if-needed.patch b/patches/server/0036-Only-refresh-abilities-if-needed.patch index 0a3babbee635..4408550aa7cb 100644 --- a/patches/server/0036-Only-refresh-abilities-if-needed.patch +++ b/patches/server/0036-Only-refresh-abilities-if-needed.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Only refresh abilities if needed diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 96300cb91f734f45ca9bcf8b7a8e727049325144..a9df824ae0a28256f3469e085c891a3a2af0fd30 100644 +index 69b4e27c6939f5a20276922714601b02d2832517..54ccf79ce6a9ca6c7ad63adb8b1bc32c1b373800 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2092,12 +2092,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2093,12 +2093,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setFlying(boolean value) { diff --git a/patches/server/0049-Use-null-Locale-by-default.patch b/patches/server/0049-Use-null-Locale-by-default.patch index e731a4f4c462..dd2e7cabdc0d 100644 --- a/patches/server/0049-Use-null-Locale-by-default.patch +++ b/patches/server/0049-Use-null-Locale-by-default.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Use null Locale by default diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 9f38010f247694e1014c9c93bfcf46d103d8fd20..1115655b1e8090c52840e85b75265da881bbc713 100644 +index 05103127d0ae220d3a27ba2bfbaa13d80ef7df7b..a9ab5b98296fe6d28d9087a7f171a0c110bc42e6 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -236,7 +236,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @@ -36,10 +36,10 @@ index 9f38010f247694e1014c9c93bfcf46d103d8fd20..1115655b1e8090c52840e85b75265da8 this.server.server.getPluginManager().callEvent(event); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index a9df824ae0a28256f3469e085c891a3a2af0fd30..4079cf3d515718a18b41333fbdc96d0c8f56648a 100644 +index 54ccf79ce6a9ca6c7ad63adb8b1bc32c1b373800..98fc35c1da6bec0fd50d2a68cbd095aaca66d91f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2422,7 +2422,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2423,7 +2423,10 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public String getLocale() { diff --git a/patches/server/0064-Disable-Scoreboards-for-non-players-by-default.patch b/patches/server/0064-Disable-Scoreboards-for-non-players-by-default.patch index fd8fbeaa15db..ba39658f013e 100644 --- a/patches/server/0064-Disable-Scoreboards-for-non-players-by-default.patch +++ b/patches/server/0064-Disable-Scoreboards-for-non-players-by-default.patch @@ -23,10 +23,10 @@ index d5f5864b7c1ad4c30f37b360b317b63c129e3a3f..82e57978b79b5275b98a1fa7731c6a23 } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index bb5e2fd7b8d9b8bec71d8c945d266765c42d3927..6e2233785fae170efb4c9611a6507dbd072416e8 100644 +index 97ad63aad3c559feb1e762af1e00fd550aa5b251..ba194f42217f1176ac08123d3bb5cb24e1a6c119 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -847,6 +847,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -848,6 +848,7 @@ public abstract class LivingEntity extends Entity implements Attackable { String s = nbt.getString("Team"); Scoreboard scoreboard = this.level().getScoreboard(); PlayerTeam scoreboardteam = scoreboard.getPlayerTeam(s); diff --git a/patches/server/0067-Complete-resource-pack-API.patch b/patches/server/0067-Complete-resource-pack-API.patch index 28173364eeaf..4128d8d8d141 100644 --- a/patches/server/0067-Complete-resource-pack-API.patch +++ b/patches/server/0067-Complete-resource-pack-API.patch @@ -22,7 +22,7 @@ index 678f12679985c6fa9effe8beec306d95d5e0bdac..8520f0f2b4b4e758b2e2fae206b7fd81 } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index bbc8f648fc8287d84a8948947e1321a47417fefa..bb4bef4e2a13aebca543136d51aa8eefead8c329 100644 +index 699248ae7c8e2b018a279ac023a0175a8af10714..f0ec24cf686fa7e1a025c8f9c8c6722f77c29e14 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -208,6 +208,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -33,7 +33,7 @@ index bbc8f648fc8287d84a8948947e1321a47417fefa..bb4bef4e2a13aebca543136d51aa8eef public CraftPlayer(CraftServer server, ServerPlayer entity) { super(server, entity); -@@ -2093,6 +2094,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2094,6 +2095,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } // Paper end - adventure diff --git a/patches/server/0071-Handle-Item-Meta-Inconsistencies.patch b/patches/server/0071-Handle-Item-Meta-Inconsistencies.patch index 33c444cddb38..2788e0342e19 100644 --- a/patches/server/0071-Handle-Item-Meta-Inconsistencies.patch +++ b/patches/server/0071-Handle-Item-Meta-Inconsistencies.patch @@ -149,7 +149,7 @@ index 21ed720118073b14bc8b5d1d665b0e17a8bbc1d2..9fa993ac05092170794911394c994fca static Map getEnchantments(net.minecraft.world.item.ItemStack item) { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index f13c703a0acafec7e6772f83ae4f5fda988cd15f..38596695282157e3ff0a53a1185d211268854c15 100644 +index 46e1fabf85cc0d92f79a7adf24e5724dc1dc08a9..69be26f8f47854f39cfed0559d944ef4f983c0f3 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -6,6 +6,7 @@ import com.google.common.collect.ImmutableList; @@ -239,7 +239,7 @@ index f13c703a0acafec7e6772f83ae4f5fda988cd15f..38596695282157e3ff0a53a1185d2112 } if (this.hasAttributeModifiers()) { clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); -@@ -2029,4 +2031,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -2028,4 +2030,22 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { return (result != null) ? result : Optional.empty(); } diff --git a/patches/server/0074-Custom-replacement-for-eaten-items.patch b/patches/server/0074-Custom-replacement-for-eaten-items.patch index 5734dd992139..ad90d60cf5d4 100644 --- a/patches/server/0074-Custom-replacement-for-eaten-items.patch +++ b/patches/server/0074-Custom-replacement-for-eaten-items.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Custom replacement for eaten items diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 6e2233785fae170efb4c9611a6507dbd072416e8..13748a5a1b2bbb8ad1ebf3c3f3d1250d9df643ea 100644 +index ba194f42217f1176ac08123d3bb5cb24e1a6c119..e7b308ba4a253b270aebebd19e2671514c5357ca 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3830,10 +3830,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3858,10 +3858,11 @@ public abstract class LivingEntity extends Entity implements Attackable { this.triggerItemUseEffects(this.useItem, 16); // CraftBukkit start - fire PlayerItemConsumeEvent ItemStack itemstack; @@ -21,7 +21,7 @@ index 6e2233785fae170efb4c9611a6507dbd072416e8..13748a5a1b2bbb8ad1ebf3c3f3d1250d this.level().getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { -@@ -3847,6 +3848,12 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3875,6 +3876,12 @@ public abstract class LivingEntity extends Entity implements Attackable { } else { itemstack = this.useItem.finishUsingItem(this.level(), this); } @@ -34,7 +34,7 @@ index 6e2233785fae170efb4c9611a6507dbd072416e8..13748a5a1b2bbb8ad1ebf3c3f3d1250d // CraftBukkit end if (itemstack != this.useItem) { -@@ -3854,6 +3861,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3882,6 +3889,11 @@ public abstract class LivingEntity extends Entity implements Attackable { } this.stopUsingItem(); diff --git a/patches/server/0075-handle-NaN-health-absorb-values-and-repair-bad-data.patch b/patches/server/0075-handle-NaN-health-absorb-values-and-repair-bad-data.patch index 18e8700307d3..90809277ffc3 100644 --- a/patches/server/0075-handle-NaN-health-absorb-values-and-repair-bad-data.patch +++ b/patches/server/0075-handle-NaN-health-absorb-values-and-repair-bad-data.patch @@ -5,10 +5,10 @@ Subject: [PATCH] handle NaN health/absorb values and repair bad data diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 13748a5a1b2bbb8ad1ebf3c3f3d1250d9df643ea..7703a5a8af59a1ebfdad49da97fbd70f838409fd 100644 +index e7b308ba4a253b270aebebd19e2671514c5357ca..fae7c493c9be741f019fc49f45a59976e6b01ed7 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -807,7 +807,13 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -808,7 +808,13 @@ public abstract class LivingEntity extends Entity implements Attackable { @Override public void readAdditionalSaveData(CompoundTag nbt) { @@ -23,7 +23,7 @@ index 13748a5a1b2bbb8ad1ebf3c3f3d1250d9df643ea..7703a5a8af59a1ebfdad49da97fbd70f if (nbt.contains("attributes", 9) && this.level() != null && !this.level().isClientSide) { this.getAttributes().load(nbt.getList("attributes", 10)); } -@@ -1341,6 +1347,10 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1342,6 +1348,10 @@ public abstract class LivingEntity extends Entity implements Attackable { } public void setHealth(float health) { @@ -34,7 +34,7 @@ index 13748a5a1b2bbb8ad1ebf3c3f3d1250d9df643ea..7703a5a8af59a1ebfdad49da97fbd70f // CraftBukkit start - Handle scaled health if (this instanceof ServerPlayer) { org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); -@@ -3660,7 +3670,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3688,7 +3698,7 @@ public abstract class LivingEntity extends Entity implements Attackable { } public final void setAbsorptionAmount(float absorptionAmount) { @@ -44,10 +44,10 @@ index 13748a5a1b2bbb8ad1ebf3c3f3d1250d9df643ea..7703a5a8af59a1ebfdad49da97fbd70f protected void internalSetAbsorptionAmount(float absorptionAmount) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index bb4bef4e2a13aebca543136d51aa8eefead8c329..a2c09546434ef8b8d8e304b83d902efd5fc36a70 100644 +index f0ec24cf686fa7e1a025c8f9c8c6722f77c29e14..8a30e4d7b6542de3e6bea37cc2a6cbabd2bb9555 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2337,6 +2337,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2338,6 +2338,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void setRealHealth(double health) { diff --git a/patches/server/0084-Add-PlayerUseUnknownEntityEvent.patch b/patches/server/0084-Add-PlayerUseUnknownEntityEvent.patch index fd655a0b9f66..cde1e3ce5287 100644 --- a/patches/server/0084-Add-PlayerUseUnknownEntityEvent.patch +++ b/patches/server/0084-Add-PlayerUseUnknownEntityEvent.patch @@ -59,10 +59,10 @@ index 64db7e017b41bffcaac202ee4ecfd7df46d69331..14a821bfc6b20475889d3138b8da9e6b @Override diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index a29dfbe7aa06113358a2078d927fc53662a5f91f..5ea0b9f215dcb457d9e34fe5e3b074843e034b0f 100644 +index 3595ff3db5eb0b1da100692702e514cb870220ee..9c0e38453e164ef394c8e1860fb92605cda71be5 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1861,4 +1861,13 @@ public class CraftEventFactory { +@@ -1880,4 +1880,13 @@ public class CraftEventFactory { Bukkit.getPluginManager().callEvent(new EntityRemoveEvent(entity.getBukkitEntity(), cause)); } diff --git a/patches/server/0092-EntityRegainHealthEvent-isFastRegen-API.patch b/patches/server/0092-EntityRegainHealthEvent-isFastRegen-API.patch index 308c3d6d6ab8..bc89e735399f 100644 --- a/patches/server/0092-EntityRegainHealthEvent-isFastRegen-API.patch +++ b/patches/server/0092-EntityRegainHealthEvent-isFastRegen-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] EntityRegainHealthEvent isFastRegen API Don't even get me started diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 7703a5a8af59a1ebfdad49da97fbd70f838409fd..369666bdbb3a68a223a75c3c519d6838bc658c40 100644 +index fae7c493c9be741f019fc49f45a59976e6b01ed7..16d611e09cbe56525cde0e0dced93b7f09c12158 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1320,10 +1320,16 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1321,10 +1321,16 @@ public abstract class LivingEntity extends Entity implements Attackable { } public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { diff --git a/patches/server/0109-Add-EntityZapEvent.patch b/patches/server/0109-Add-EntityZapEvent.patch index c7a81aa78aef..0e8081190876 100644 --- a/patches/server/0109-Add-EntityZapEvent.patch +++ b/patches/server/0109-Add-EntityZapEvent.patch @@ -28,10 +28,10 @@ index 63c10be6eacd7108b8b4795d76bf624e0614440a..243eb1e54293c763a06febff551c0513 entitywitch.finalizeSpawn(world, world.getCurrentDifficultyAt(entitywitch.blockPosition()), MobSpawnType.CONVERSION, (SpawnGroupData) null); entitywitch.setNoAi(this.isNoAi()); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 5ea0b9f215dcb457d9e34fe5e3b074843e034b0f..8071c04be18b67a9f12fb92154c0fd19769972ab 100644 +index 9c0e38453e164ef394c8e1860fb92605cda71be5..ba8dfea4a88cb9ba881cd90dfb5d41087498ae54 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1198,6 +1198,14 @@ public class CraftEventFactory { +@@ -1202,6 +1202,14 @@ public class CraftEventFactory { return !event.isCancelled(); } diff --git a/patches/server/0113-Add-source-to-PlayerExpChangeEvent.patch b/patches/server/0113-Add-source-to-PlayerExpChangeEvent.patch index 45e4d30d6a81..b739ee335103 100644 --- a/patches/server/0113-Add-source-to-PlayerExpChangeEvent.patch +++ b/patches/server/0113-Add-source-to-PlayerExpChangeEvent.patch @@ -18,10 +18,10 @@ index 56402312e44d12c859e2c4b39902d31b7cfd1573..25a45e680f9fdea90f43d59de87a3a50 --this.count; diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 8071c04be18b67a9f12fb92154c0fd19769972ab..ad799d1d0f46663d5bc850763629f430d00b58fe 100644 +index ba8dfea4a88cb9ba881cd90dfb5d41087498ae54..a3a63c5988eaa987a3718dfa79876e81d05e7fa6 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1151,6 +1151,17 @@ public class CraftEventFactory { +@@ -1155,6 +1155,17 @@ public class CraftEventFactory { return event; } diff --git a/patches/server/0114-Add-ProjectileCollideEvent.patch b/patches/server/0114-Add-ProjectileCollideEvent.patch index 0ace0199a8be..df432de74e4d 100644 --- a/patches/server/0114-Add-ProjectileCollideEvent.patch +++ b/patches/server/0114-Add-ProjectileCollideEvent.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add ProjectileCollideEvent Deprecated now and replaced with ProjectileHitEvent diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index ad799d1d0f46663d5bc850763629f430d00b58fe..a4060019e30f6fc64e10494ed41d6613d1b894d7 100644 +index a3a63c5988eaa987a3718dfa79876e81d05e7fa6..0aa10b1709c195d766eb49e21d9bc19d7cecf760 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1295,6 +1295,17 @@ public class CraftEventFactory { +@@ -1299,6 +1299,17 @@ public class CraftEventFactory { return CraftItemStack.asNMSCopy(bitem); } @@ -27,7 +27,7 @@ index ad799d1d0f46663d5bc850763629f430d00b58fe..a4060019e30f6fc64e10494ed41d6613 public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) { Projectile bukkitEntity = (Projectile) entity.getBukkitEntity(); ProjectileLaunchEvent event = new ProjectileLaunchEvent(bukkitEntity); -@@ -1319,8 +1330,15 @@ public class CraftEventFactory { +@@ -1323,8 +1334,15 @@ public class CraftEventFactory { if (position.getType() == HitResult.Type.ENTITY) { hitEntity = ((EntityHitResult) position).getEntity().getBukkitEntity(); } diff --git a/patches/server/0121-Properly-fix-item-duplication-bug.patch b/patches/server/0121-Properly-fix-item-duplication-bug.patch index 60bdf7de86db..86782af8c70b 100644 --- a/patches/server/0121-Properly-fix-item-duplication-bug.patch +++ b/patches/server/0121-Properly-fix-item-duplication-bug.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Properly fix item duplication bug Credit to prplz for figuring out the real issue diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 70f0f4daff27754aefcadb84387bb3054cc66a8e..dae729c39e5d3fefc8188069e81f33066746c4a6 100644 +index ac4b66a4aa9e2f186ed5ff3c7d41a01152a9d283..e7b39f06707a62d26af7e183413e0301501d2ce0 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2623,7 +2623,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { +@@ -2630,7 +2630,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @Override public boolean isImmobile() { diff --git a/patches/server/0126-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch b/patches/server/0126-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch index 8fc035b6bfed..68a1c8b37a6f 100644 --- a/patches/server/0126-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch +++ b/patches/server/0126-ExperienceOrbs-API-for-Reason-Source-Triggering-play.patch @@ -127,10 +127,10 @@ index 25a45e680f9fdea90f43d59de87a3a500f4ee8c0..0330a62a6a0060d2a96de191db687745 @Override diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 369666bdbb3a68a223a75c3c519d6838bc658c40..cacada8cfbe171cdb10aa2a78483ef3b613b414a 100644 +index 16d611e09cbe56525cde0e0dced93b7f09c12158..b6a7c9ee6e6885e0cc44e2f2ff3ea7bba9cb8f3d 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1788,7 +1788,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1799,7 +1799,7 @@ public abstract class LivingEntity extends Entity implements Attackable { protected void dropExperience(@Nullable Entity attacker) { // CraftBukkit start - Update getExpReward() above if the removed if() changes! if (!(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time @@ -140,10 +140,10 @@ index 369666bdbb3a68a223a75c3c519d6838bc658c40..cacada8cfbe171cdb10aa2a78483ef3b } // CraftBukkit end diff --git a/src/main/java/net/minecraft/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java -index 1af60680c512e0743920440215247d191f9a8385..370c444153d04fe7896952219604d83a19a996e2 100644 +index 48d0cbe7859c62bbf281a7b43ef9af658667cb7b..b46352b328178df2a48d1c9e895bed3fabd2c292 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Animal.java +++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java -@@ -250,12 +250,14 @@ public abstract class Animal extends AgeableMob { +@@ -251,12 +251,14 @@ public abstract class Animal extends AgeableMob { public void finalizeSpawnChildFromBreeding(ServerLevel worldserver, Animal entityanimal, @Nullable AgeableMob entityageable, int experience) { // CraftBukkit end @@ -162,7 +162,7 @@ index 1af60680c512e0743920440215247d191f9a8385..370c444153d04fe7896952219604d83a this.setAge(6000); entityanimal.setAge(6000); this.resetLove(); -@@ -264,7 +266,7 @@ public abstract class Animal extends AgeableMob { +@@ -265,7 +267,7 @@ public abstract class Animal extends AgeableMob { if (worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // CraftBukkit start - use event experience if (experience > 0) { diff --git a/patches/server/0127-Cap-Entity-Collisions.patch b/patches/server/0127-Cap-Entity-Collisions.patch index 0c7b93037aab..8feda191fe79 100644 --- a/patches/server/0127-Cap-Entity-Collisions.patch +++ b/patches/server/0127-Cap-Entity-Collisions.patch @@ -24,10 +24,10 @@ index bd17157631a74f80e3b5ce50bb1f681abe1dd6a7..46a21ed2408a42aafd16647e17e55673 @javax.annotation.Nullable private org.bukkit.util.Vector origin; diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index cacada8cfbe171cdb10aa2a78483ef3b613b414a..51dadc6d3ea7f0b7b5eb5117b58df0e532c65eb9 100644 +index b6a7c9ee6e6885e0cc44e2f2ff3ea7bba9cb8f3d..f297b2227d0793f44cb5770aa24a474ec7283b15 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3474,10 +3474,12 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3502,10 +3502,12 @@ public abstract class LivingEntity extends Entity implements Attackable { } Iterator iterator1 = list.iterator(); diff --git a/patches/server/0129-Properly-handle-async-calls-to-restart-the-server.patch b/patches/server/0129-Properly-handle-async-calls-to-restart-the-server.patch index 6bab23ed9ed3..37a92c3e7121 100644 --- a/patches/server/0129-Properly-handle-async-calls-to-restart-the-server.patch +++ b/patches/server/0129-Properly-handle-async-calls-to-restart-the-server.patch @@ -84,7 +84,7 @@ index e17f4f3882ae77a67e8bfad04646f02c2bbb6669..d5f17d7e3b56ca87ec9070b69265ce09 } // CraftBukkit end diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index c30f9899ec5529e49919367ab4e0ae797b429afa..9a1fffa0c07c24eed8bd6ea8f3cd26c9f926c54d 100644 +index de8c703803bcd074f765a44cabc7c635176b716d..824c4ad135ea5177f416687c7042639ed126b70b 100644 --- a/src/main/java/org/spigotmc/RestartCommand.java +++ b/src/main/java/org/spigotmc/RestartCommand.java @@ -46,86 +46,134 @@ public class RestartCommand extends Command @@ -119,7 +119,7 @@ index c30f9899ec5529e49919367ab4e0ae797b429afa..9a1fffa0c07c24eed8bd6ea8f3cd26c9 - // Kick all players - for ( ServerPlayer p : (List) MinecraftServer.getServer().getPlayerList().players ) - { -- p.connection.disconnect( CraftChatMessage.fromStringOrEmpty( SpigotConfig.restartMessage ) ); +- p.connection.disconnect( CraftChatMessage.fromStringOrEmpty( SpigotConfig.restartMessage, true ) ); - } - // Give the socket a chance to send the packets - try @@ -138,7 +138,7 @@ index c30f9899ec5529e49919367ab4e0ae797b429afa..9a1fffa0c07c24eed8bd6ea8f3cd26c9 + // Kick all players + for ( ServerPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) + { -+ p.connection.disconnect( CraftChatMessage.fromStringOrEmpty( SpigotConfig.restartMessage ) ); ++ p.connection.disconnect( CraftChatMessage.fromStringOrEmpty( SpigotConfig.restartMessage, true ) ); + } + // Give the socket a chance to send the packets + try diff --git a/patches/server/0130-Add-option-to-make-parrots-stay-on-shoulders-despite.patch b/patches/server/0130-Add-option-to-make-parrots-stay-on-shoulders-despite.patch index 874f766d13b4..20b540764e2e 100644 --- a/patches/server/0130-Add-option-to-make-parrots-stay-on-shoulders-despite.patch +++ b/patches/server/0130-Add-option-to-make-parrots-stay-on-shoulders-despite.patch @@ -32,10 +32,10 @@ index 34aeb823950fac8eaef3f38b302c1585a45f7498..44cc60d92c6e83ecfa2c232b59986968 case RELEASE_SHIFT_KEY: this.player.setShiftKeyDown(false); diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 0d1d8ad353ff2f2bd478cfdc2f6bebad5203e190..c9423872c23f3334afad34e662041c5f5d1ad1a2 100644 +index ba279ab6ec0ab41309607333b62a941e35dbf581..7995a4626b3ed68234d468418408b9a8e179b6f6 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -592,6 +592,7 @@ public abstract class Player extends LivingEntity { +@@ -593,6 +593,7 @@ public abstract class Player extends LivingEntity { this.playShoulderEntityAmbientSound(this.getShoulderEntityLeft()); this.playShoulderEntityAmbientSound(this.getShoulderEntityRight()); if (!this.level().isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.flying || this.isSleeping() || this.isInPowderSnow) { diff --git a/patches/server/0139-Shoulder-Entities-Release-API.patch b/patches/server/0139-Shoulder-Entities-Release-API.patch index 9facd3b0cfcf..b0762a4548ed 100644 --- a/patches/server/0139-Shoulder-Entities-Release-API.patch +++ b/patches/server/0139-Shoulder-Entities-Release-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Shoulder Entities Release API diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index c9423872c23f3334afad34e662041c5f5d1ad1a2..d603a7211c7e7eb2567881a530ae7bcbc8def5a6 100644 +index 7995a4626b3ed68234d468418408b9a8e179b6f6..362d75522aaa721e9fb1d12a149d0efec1ac17b1 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1992,20 +1992,45 @@ public abstract class Player extends LivingEntity { +@@ -1995,20 +1995,45 @@ public abstract class Player extends LivingEntity { } @@ -59,10 +59,10 @@ index c9423872c23f3334afad34e662041c5f5d1ad1a2..d603a7211c7e7eb2567881a530ae7bcb @Override public abstract boolean isSpectator(); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 1010ac55d91559bcb6ebadeea447f32c6aa89226..47350439f579ef2ab408bda0fc4b8976df3a5b92 100644 +index 0c94a1094a3af0232bb2957708fa997933db621b..9574d5e0ee9109155f16861d0c46e45ef4c1d1a8 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -511,6 +511,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -512,6 +512,32 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { this.getHandle().getCooldowns().addCooldown(CraftItemType.bukkitToMinecraft(material), ticks); } diff --git a/patches/server/0147-Fix-this-stupid-bullshit.patch b/patches/server/0147-Fix-this-stupid-bullshit.patch index cc049a1a33f4..06f8ccc1c59b 100644 --- a/patches/server/0147-Fix-this-stupid-bullshit.patch +++ b/patches/server/0147-Fix-this-stupid-bullshit.patch @@ -31,12 +31,12 @@ index 8f1992188f7fd9e735569e099b36a7eafed47aae..061c89b985dafc79c808dd5f0e296b9f Bootstrap.isBootstrapped = true; Instant instant = Instant.now(); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index 9515a6f72b54bc8926f10182143b2aa9b684a341..faa228698c7dd60bde0f3767cc27957ece04b8be 100644 +index 75a3c7ed5500f0451c9c1efdfc3cb809445c8acf..8245b38d37b4cee6f4e7b61d7af40a18e54a3f43 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -260,10 +260,12 @@ public class Main { Calendar deadline = Calendar.getInstance(); - deadline.add(Calendar.DAY_OF_YEAR, -3); + deadline.add(Calendar.DAY_OF_YEAR, -7); if (buildDate.before(deadline.getTime())) { - System.err.println("*** Error, this build is outdated ***"); + // Paper start - This is some stupid bullshit diff --git a/patches/server/0156-Send-attack-SoundEffects-only-to-players-who-can-see.patch b/patches/server/0156-Send-attack-SoundEffects-only-to-players-who-can-see.patch index 94f8863d3bbb..f4f07b3245b9 100644 --- a/patches/server/0156-Send-attack-SoundEffects-only-to-players-who-can-see.patch +++ b/patches/server/0156-Send-attack-SoundEffects-only-to-players-who-can-see.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Send attack SoundEffects only to players who can see the diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index d603a7211c7e7eb2567881a530ae7bcbc8def5a6..b62f7ae1929513bd6da90bc91e3654c28c28a40a 100644 +index 362d75522aaa721e9fb1d12a149d0efec1ac17b1..34654395536ea022848db3d9f0291512081fc558 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1256,7 +1256,7 @@ public abstract class Player extends LivingEntity { +@@ -1257,7 +1257,7 @@ public abstract class Player extends LivingEntity { boolean flag1; if (this.isSprinting() && flag) { @@ -18,7 +18,7 @@ index d603a7211c7e7eb2567881a530ae7bcbc8def5a6..b62f7ae1929513bd6da90bc91e3654c2 flag1 = true; } else { flag1 = false; -@@ -1335,7 +1335,7 @@ public abstract class Player extends LivingEntity { +@@ -1338,7 +1338,7 @@ public abstract class Player extends LivingEntity { } } @@ -27,7 +27,7 @@ index d603a7211c7e7eb2567881a530ae7bcbc8def5a6..b62f7ae1929513bd6da90bc91e3654c2 this.sweepAttack(); } -@@ -1363,15 +1363,15 @@ public abstract class Player extends LivingEntity { +@@ -1366,15 +1366,15 @@ public abstract class Player extends LivingEntity { } if (flag2) { @@ -46,7 +46,7 @@ index d603a7211c7e7eb2567881a530ae7bcbc8def5a6..b62f7ae1929513bd6da90bc91e3654c2 } } -@@ -1427,7 +1427,7 @@ public abstract class Player extends LivingEntity { +@@ -1430,7 +1430,7 @@ public abstract class Player extends LivingEntity { this.causeFoodExhaustion(this.level().spigotConfig.combatExhaustion, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent // Spigot - Change to use configurable value } else { @@ -55,7 +55,7 @@ index d603a7211c7e7eb2567881a530ae7bcbc8def5a6..b62f7ae1929513bd6da90bc91e3654c2 // CraftBukkit start - resync on cancelled event if (this instanceof ServerPlayer) { ((ServerPlayer) this).getBukkitEntity().updateInventory(); -@@ -1822,6 +1822,14 @@ public abstract class Player extends LivingEntity { +@@ -1825,6 +1825,14 @@ public abstract class Player extends LivingEntity { public int getXpNeededForNextLevel() { return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2); } diff --git a/patches/server/0157-Add-PlayerArmorChangeEvent.patch b/patches/server/0157-Add-PlayerArmorChangeEvent.patch index 8e7a7da4ed5b..d9478284f827 100644 --- a/patches/server/0157-Add-PlayerArmorChangeEvent.patch +++ b/patches/server/0157-Add-PlayerArmorChangeEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add PlayerArmorChangeEvent diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 51dadc6d3ea7f0b7b5eb5117b58df0e532c65eb9..71696a99a99573aa54c11ee9b490bb292d59f753 100644 +index f297b2227d0793f44cb5770aa24a474ec7283b15..21d00a73ad8287d61eda1ab91b88ea3264aff021 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3140,6 +3140,13 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3168,6 +3168,13 @@ public abstract class LivingEntity extends Entity implements Attackable { ItemStack itemstack2 = this.getItemBySlot(enumitemslot); if (this.equipmentHasChanged(itemstack1, itemstack2)) { diff --git a/patches/server/0164-Ability-to-apply-mending-to-XP-API.patch b/patches/server/0164-Ability-to-apply-mending-to-XP-API.patch index fd8b6478902b..5b73d571fbe6 100644 --- a/patches/server/0164-Ability-to-apply-mending-to-XP-API.patch +++ b/patches/server/0164-Ability-to-apply-mending-to-XP-API.patch @@ -14,10 +14,10 @@ public net.minecraft.world.entity.ExperienceOrb durabilityToXp(I)I public net.minecraft.world.entity.ExperienceOrb xpToDurability(I)I diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 9eddc3ac16645e0a01cc5c2decc8e53f08e7e3dc..aaef5693b044141d2aa8108b74b240903c64e6e6 100644 +index 8d2c795d8898cd32611366b972b35d132c22eca7..f85711a2ff57498f385da7da9b77ec130aff116b 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1637,7 +1637,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1638,7 +1638,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override diff --git a/patches/server/0173-Toggleable-player-crits.patch b/patches/server/0173-Toggleable-player-crits.patch index 6e4e9c5ff2e6..03d3f5c4f1e0 100644 --- a/patches/server/0173-Toggleable-player-crits.patch +++ b/patches/server/0173-Toggleable-player-crits.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Toggleable player crits diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index b62f7ae1929513bd6da90bc91e3654c28c28a40a..d365fd0fa03a773b21b64f0a84a8b2d83a740845 100644 +index 34654395536ea022848db3d9f0291512081fc558..3f0425f6c1a8d5ad4df9d837490c09e175d0df4b 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1265,6 +1265,7 @@ public abstract class Player extends LivingEntity { +@@ -1266,6 +1266,7 @@ public abstract class Player extends LivingEntity { f += itemstack.getItem().getAttackDamageBonus(target, f, damagesource); boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity && !this.isSprinting(); diff --git a/patches/server/0177-Player.setPlayerProfile-API.patch b/patches/server/0177-Player.setPlayerProfile-API.patch index cec219427faf..38ad4142e9b7 100644 --- a/patches/server/0177-Player.setPlayerProfile-API.patch +++ b/patches/server/0177-Player.setPlayerProfile-API.patch @@ -77,7 +77,7 @@ index 818df09e9245b5d89b4180b1eaa51470b7539341..461656e1cb095243bfe7a9ee2906e5b0 public Server getServer() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index aaef5693b044141d2aa8108b74b240903c64e6e6..a6567aa9a3ec9dd17689e907131e5cca05da7c9d 100644 +index f85711a2ff57498f385da7da9b77ec130aff116b..f7534be64cdbf1342b523ef2ab0627f597983e0d 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -249,11 +249,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -92,7 +92,7 @@ index aaef5693b044141d2aa8108b74b240903c64e6e6..a6567aa9a3ec9dd17689e907131e5cca @Override public InetSocketAddress getAddress() { if (this.getHandle().connection.protocol() == null) return null; -@@ -1791,8 +1786,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1792,8 +1787,15 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private void untrackAndHideEntity(org.bukkit.entity.Entity entity) { // Remove this entity from the hidden player's EntityTrackerEntry @@ -109,7 +109,7 @@ index aaef5693b044141d2aa8108b74b240903c64e6e6..a6567aa9a3ec9dd17689e907131e5cca ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); if (entry != null) { entry.removePlayer(this.getHandle()); -@@ -1805,8 +1807,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1806,8 +1808,6 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().connection.send(new ClientboundPlayerInfoRemovePacket(List.of(otherPlayer.getUUID()))); } } @@ -118,7 +118,7 @@ index aaef5693b044141d2aa8108b74b240903c64e6e6..a6567aa9a3ec9dd17689e907131e5cca } void resetAndHideEntity(org.bukkit.entity.Entity entity) { -@@ -1871,12 +1871,25 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1872,12 +1872,25 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } private void trackAndShowEntity(org.bukkit.entity.Entity entity) { @@ -144,7 +144,7 @@ index aaef5693b044141d2aa8108b74b240903c64e6e6..a6567aa9a3ec9dd17689e907131e5cca } ChunkMap.TrackedEntity entry = tracker.entityMap.get(other.getId()); -@@ -1886,6 +1899,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1887,6 +1900,39 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.server.getPluginManager().callEvent(new PlayerShowEntityEvent(this, entity)); } @@ -184,7 +184,7 @@ index aaef5693b044141d2aa8108b74b240903c64e6e6..a6567aa9a3ec9dd17689e907131e5cca void resetAndShowEntity(org.bukkit.entity.Entity entity) { // SPIGOT-7312: Can't show/hide self -@@ -1897,6 +1943,34 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1898,6 +1944,34 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.trackAndShowEntity(entity); } } @@ -220,10 +220,10 @@ index aaef5693b044141d2aa8108b74b240903c64e6e6..a6567aa9a3ec9dd17689e907131e5cca public void onEntityRemove(Entity entity) { this.invertedVisibilityEntities.remove(entity.getUUID()); diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -index 8757d4de8a589355b83690d37d9e81ce3cc6ae32..93c0390aade242bc24f8d9a9ac99242d0f588d5e 100644 +index 0bde8fc63d892cb615638769ca84beba9da80ff2..a2b1197a26eed4df77d7f770e016f522832d8aa2 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -@@ -394,6 +394,13 @@ public class Commodore { +@@ -404,6 +404,13 @@ public class Commodore { } // Paper end - Rewrite plugins diff --git a/patches/server/0182-Flag-to-disable-the-channel-limit.patch b/patches/server/0182-Flag-to-disable-the-channel-limit.patch index eb219a5de168..61d82fcade0f 100644 --- a/patches/server/0182-Flag-to-disable-the-channel-limit.patch +++ b/patches/server/0182-Flag-to-disable-the-channel-limit.patch @@ -9,7 +9,7 @@ e.g. servers which allow and support the usage of mod packs. provide an optional flag to disable this check, at your own risk. diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index a6567aa9a3ec9dd17689e907131e5cca05da7c9d..27298cd0558b1ff2ab2ca341d62da2922507414b 100644 +index f7534be64cdbf1342b523ef2ab0627f597983e0d..24928a1e12ecedaaa634be0ab5425ee77b0f6556 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -209,6 +209,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -20,7 +20,7 @@ index a6567aa9a3ec9dd17689e907131e5cca05da7c9d..27298cd0558b1ff2ab2ca341d62da292 public CraftPlayer(CraftServer server, ServerPlayer entity) { super(server, entity); -@@ -2268,7 +2269,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2269,7 +2270,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void addChannel(String channel) { diff --git a/patches/server/0183-Add-openSign-method-to-HumanEntity.patch b/patches/server/0183-Add-openSign-method-to-HumanEntity.patch index 969c29ccc9e9..83658d2f8b4d 100644 --- a/patches/server/0183-Add-openSign-method-to-HumanEntity.patch +++ b/patches/server/0183-Add-openSign-method-to-HumanEntity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add openSign method to HumanEntity diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 47350439f579ef2ab408bda0fc4b8976df3a5b92..dd3377a4f69e5ac10905e52d0eecc2427e72d856 100644 +index 9574d5e0ee9109155f16861d0c46e45ef4c1d1a8..2e02fc22a889c9c8010ae8bff1b59a13219ae014 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -621,6 +621,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -622,6 +622,12 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { } } diff --git a/patches/server/0184-Configurable-sprint-interruption-on-attack.patch b/patches/server/0184-Configurable-sprint-interruption-on-attack.patch index 28d5c976c048..65dd42f5eb59 100644 --- a/patches/server/0184-Configurable-sprint-interruption-on-attack.patch +++ b/patches/server/0184-Configurable-sprint-interruption-on-attack.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Configurable sprint interruption on attack If the sprint interruption is disabled players continue sprinting when they attack entities. diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index d365fd0fa03a773b21b64f0a84a8b2d83a740845..8977aaa75b287cbd13ed18a5ee5ba950fcd738e6 100644 +index 3f0425f6c1a8d5ad4df9d837490c09e175d0df4b..00fecf255214d87837867b8743cc8f161ebfcb4c 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1306,7 +1306,11 @@ public abstract class Player extends LivingEntity { +@@ -1307,7 +1307,11 @@ public abstract class Player extends LivingEntity { } this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); diff --git a/patches/server/0193-WitchReadyPotionEvent.patch b/patches/server/0193-WitchReadyPotionEvent.patch index fbda7c03d73c..6581d99e3155 100644 --- a/patches/server/0193-WitchReadyPotionEvent.patch +++ b/patches/server/0193-WitchReadyPotionEvent.patch @@ -22,10 +22,10 @@ index a14e00d55930628333cc63b18727ea56dbdc4ee3..f6d01d21745391595d61b191832be4c2 this.setUsingItem(true); if (!this.isSilent()) { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index a4060019e30f6fc64e10494ed41d6613d1b894d7..587437f995dd411c051f2125202f1a48cfc1bb1b 100644 +index 0aa10b1709c195d766eb49e21d9bc19d7cecf760..9c463d551fc402dbcbc81aad5251a9183596830a 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1907,4 +1907,14 @@ public class CraftEventFactory { +@@ -1926,4 +1926,14 @@ public class CraftEventFactory { ).callEvent(); } // Paper end - PlayerUseUnknownEntityEvent diff --git a/patches/server/0200-Make-shield-blocking-delay-configurable.patch b/patches/server/0200-Make-shield-blocking-delay-configurable.patch index c072b62e7b9c..9468400c1063 100644 --- a/patches/server/0200-Make-shield-blocking-delay-configurable.patch +++ b/patches/server/0200-Make-shield-blocking-delay-configurable.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Make shield blocking delay configurable diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 71696a99a99573aa54c11ee9b490bb292d59f753..a054aaa3713f911512358cbd63c202a8a7bb8236 100644 +index 21d00a73ad8287d61eda1ab91b88ea3264aff021..cccc60602360f25f0aeddbd16dad2bb63a1728a8 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3938,12 +3938,24 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3966,12 +3966,24 @@ public abstract class LivingEntity extends Entity implements Attackable { if (this.isUsingItem() && !this.useItem.isEmpty()) { Item item = this.useItem.getItem(); diff --git a/patches/server/0202-PlayerReadyArrowEvent.patch b/patches/server/0202-PlayerReadyArrowEvent.patch index d6e29005bd8b..37f2fbca4e11 100644 --- a/patches/server/0202-PlayerReadyArrowEvent.patch +++ b/patches/server/0202-PlayerReadyArrowEvent.patch @@ -7,10 +7,10 @@ Called when a player is firing a bow and the server is choosing an arrow to use. Plugins can skip selection of certain arrows and control which is used. diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 8977aaa75b287cbd13ed18a5ee5ba950fcd738e6..f21d121418872f5ece763f33c15091e787991d7c 100644 +index 00fecf255214d87837867b8743cc8f161ebfcb4c..d6bbeaf3833a4c44ed05243445edd813e3f15dcb 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -2229,18 +2229,29 @@ public abstract class Player extends LivingEntity { +@@ -2232,18 +2232,29 @@ public abstract class Player extends LivingEntity { return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING); } diff --git a/patches/server/0203-Add-entity-knockback-events.patch b/patches/server/0203-Add-entity-knockback-events.patch index 2a626e60e965..c87dbadcd6ee 100644 --- a/patches/server/0203-Add-entity-knockback-events.patch +++ b/patches/server/0203-Add-entity-knockback-events.patch @@ -38,10 +38,10 @@ index d6017d9d71fb4b3a3df6eaa44da0ebda54c83da4..629942afb41f73ca7a7855cba58c81fd } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index a054aaa3713f911512358cbd63c202a8a7bb8236..ebd81b34d1fbb31ce0f9c92593154fdb6b62bf52 100644 +index cccc60602360f25f0aeddbd16dad2bb63a1728a8..bf1b8ee85551ff1989369268edf8012758b86fd7 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1517,7 +1517,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1528,7 +1528,7 @@ public abstract class LivingEntity extends Entity implements Attackable { d1 = source.getSourcePosition().z() - this.getZ(); } @@ -50,7 +50,7 @@ index a054aaa3713f911512358cbd63c202a8a7bb8236..ebd81b34d1fbb31ce0f9c92593154fdb if (!flag) { this.indicateDamage(d0, d1); } -@@ -1570,7 +1570,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1581,7 +1581,7 @@ public abstract class LivingEntity extends Entity implements Attackable { } protected void blockedByShield(LivingEntity target) { @@ -59,7 +59,7 @@ index a054aaa3713f911512358cbd63c202a8a7bb8236..ebd81b34d1fbb31ce0f9c92593154fdb } private boolean checkTotemDeathProtection(DamageSource source) { -@@ -1831,10 +1831,10 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1842,10 +1842,10 @@ public abstract class LivingEntity extends Entity implements Attackable { public void knockback(double strength, double x, double z) { // CraftBukkit start - EntityKnockbackEvent @@ -72,7 +72,7 @@ index a054aaa3713f911512358cbd63c202a8a7bb8236..ebd81b34d1fbb31ce0f9c92593154fdb d0 *= 1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); if (true || d0 > 0.0D) { // CraftBukkit - Call event even when force is 0 //this.hasImpulse = true; // CraftBukkit - Move down -@@ -1847,13 +1847,17 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1858,13 +1858,17 @@ public abstract class LivingEntity extends Entity implements Attackable { Vec3 vec3d1 = (new Vec3(d1, 0.0D, d2)).normalize().scale(d0); @@ -200,10 +200,10 @@ index a6c33abcbbfc0851c8fa979163de145a578f97a6..18389b3befe31b224010e55244fbcb7c } } diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index f21d121418872f5ece763f33c15091e787991d7c..3512f0b309c7822f7b9d9eacbcf4dd84d9c24896 100644 +index d6bbeaf3833a4c44ed05243445edd813e3f15dcb..1b13096da1f0bc49efe25677ec24e6abe7ff2879 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1300,9 +1300,9 @@ public abstract class Player extends LivingEntity { +@@ -1301,9 +1301,9 @@ public abstract class Player extends LivingEntity { if (target instanceof LivingEntity) { LivingEntity entityliving1 = (LivingEntity) target; @@ -215,15 +215,15 @@ index f21d121418872f5ece763f33c15091e787991d7c..3512f0b309c7822f7b9d9eacbcf4dd84 } this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D)); -@@ -1327,7 +1327,7 @@ public abstract class Player extends LivingEntity { - - // CraftBukkit start - Only apply knockback if the damage hits - if (entityliving2.hurt(this.damageSources().playerAttack(this).sweep(), f7)) { -- entityliving2.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, EntityKnockbackEvent.KnockbackCause.SWEEP_ATTACK); // CraftBukkit -+ entityliving2.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.SWEEP_ATTACK); // CraftBukkit // Paper - knockback events +@@ -1331,7 +1331,7 @@ public abstract class Player extends LivingEntity { + continue; } // CraftBukkit end +- entityliving2.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F))); ++ entityliving2.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)), this, io.papermc.paper.event.entity.EntityKnockbackEvent.Cause.SWEEP_ATTACK); // CraftBukkit // Paper - knockback events + // entityliving2.hurt(damagesource, f7); // CraftBukkit - moved up Level world = this.level(); + diff --git a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java b/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java index 230040bef7d2cf9a463cfd9cb3b1b1aa208a7119..6c79997ba46e641de5aa12ff8a3d790d04a5a475 100644 --- a/src/main/java/net/minecraft/world/entity/projectile/AbstractArrow.java @@ -273,10 +273,10 @@ index d93ed33d5ae72e9dd3e6cf044ef79e4b9689dc1c..512d79b66fed3d1bef645c3ecb59bda0 // CraftBukkit end entity.setDeltaMovement(entity.getDeltaMovement().add(vec3d1)); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 587437f995dd411c051f2125202f1a48cfc1bb1b..86bddb9c39d8487f050d126dbb479315cb8a2818 100644 +index 9c463d551fc402dbcbc81aad5251a9183596830a..cf045e3ebe75046212755f18058bf4381bacacc1 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1869,19 +1869,33 @@ public class CraftEventFactory { +@@ -1888,19 +1888,33 @@ public class CraftEventFactory { return event; } diff --git a/patches/server/0209-InventoryCloseEvent-Reason-API.patch b/patches/server/0209-InventoryCloseEvent-Reason-API.patch index 8337d0eb9071..9a7d5952e683 100644 --- a/patches/server/0209-InventoryCloseEvent-Reason-API.patch +++ b/patches/server/0209-InventoryCloseEvent-Reason-API.patch @@ -29,7 +29,7 @@ index 5bf18ab5c397b32d880ea1827f62945d8d0e80ce..ce6be7aed7b392c3e0c851f3f6e1e216 } // Spigot End diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 809a4f403695240b507528fb8fa3f7d390f86349..622f890d2613acf948b68d6febe0834ceec23c80 100644 +index 2e66315859c9374ae77288c35aaddf56d60cf0a2..7c00c4244233cee313127c1e8c06ef9288d5b9b1 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -707,7 +707,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @@ -109,10 +109,10 @@ index 9019e25f61d4fdb7c5d12ea7630b0bc23827ab6e..38cf3cf1cc7ebae4b6ca8a89dc026b5b PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(entityplayer.getBukkitEntity(), net.kyori.adventure.text.Component.translatable("multiplayer.player.left", net.kyori.adventure.text.format.NamedTextColor.YELLOW, io.papermc.paper.configuration.GlobalConfiguration.get().messages.useDisplayNameInQuitMessage ? entityplayer.getBukkitEntity().displayName() : io.papermc.paper.adventure.PaperAdventure.asAdventure(entityplayer.getDisplayName()))); // Paper - Adventure diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 3512f0b309c7822f7b9d9eacbcf4dd84d9c24896..e60da80cbc2d2dbb98287470e1741fa2a3f95335 100644 +index 1b13096da1f0bc49efe25677ec24e6abe7ff2879..b70fbc1a93271bbf28402afbe9c6e538a4b6e9aa 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -278,7 +278,7 @@ public abstract class Player extends LivingEntity { +@@ -279,7 +279,7 @@ public abstract class Player extends LivingEntity { this.updateIsUnderwater(); super.tick(); if (!this.level().isClientSide && this.containerMenu != null && !this.containerMenu.stillValid(this)) { @@ -121,7 +121,7 @@ index 3512f0b309c7822f7b9d9eacbcf4dd84d9c24896..e60da80cbc2d2dbb98287470e1741fa2 this.containerMenu = this.inventoryMenu; } -@@ -496,6 +496,13 @@ public abstract class Player extends LivingEntity { +@@ -497,6 +497,13 @@ public abstract class Player extends LivingEntity { } @@ -136,10 +136,10 @@ index 3512f0b309c7822f7b9d9eacbcf4dd84d9c24896..e60da80cbc2d2dbb98287470e1741fa2 this.containerMenu = this.inventoryMenu; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index dd3377a4f69e5ac10905e52d0eecc2427e72d856..c79607a2f45b7a487a95cf98b9b0eb6b36501410 100644 +index 2e02fc22a889c9c8010ae8bff1b59a13219ae014..703bb1bb42b1668c04824489fd2f349052025979 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -377,7 +377,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -378,7 +378,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { if (((ServerPlayer) this.getHandle()).connection == null) return; if (this.getHandle().containerMenu != this.getHandle().inventoryMenu) { // fire INVENTORY_CLOSE if one already open @@ -148,7 +148,7 @@ index dd3377a4f69e5ac10905e52d0eecc2427e72d856..c79607a2f45b7a487a95cf98b9b0eb6b } ServerPlayer player = (ServerPlayer) this.getHandle(); AbstractContainerMenu container; -@@ -447,8 +447,14 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -448,8 +448,14 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @Override public void closeInventory() { @@ -165,7 +165,7 @@ index dd3377a4f69e5ac10905e52d0eecc2427e72d856..c79607a2f45b7a487a95cf98b9b0eb6b @Override public boolean isBlocking() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 27298cd0558b1ff2ab2ca341d62da2922507414b..38bc1747d2010b9233c64de81eb1c042bd1357b5 100644 +index 24928a1e12ecedaaa634be0ab5425ee77b0f6556..62c9f17fc4eeb5d26bfbeabad53016d959198393 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1273,7 +1273,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -178,10 +178,10 @@ index 27298cd0558b1ff2ab2ca341d62da2922507414b..38bc1747d2010b9233c64de81eb1c042 // Check if the fromWorld and toWorld are the same. diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 86bddb9c39d8487f050d126dbb479315cb8a2818..8d86649579cb7eb90e3866ed81f2ba4f342f8b1c 100644 +index cf045e3ebe75046212755f18058bf4381bacacc1..836eba2f7b4260e5f882b202ef5923bb9bcfcd58 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1264,7 +1264,7 @@ public class CraftEventFactory { +@@ -1268,7 +1268,7 @@ public class CraftEventFactory { public static AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container, boolean cancelled) { if (player.containerMenu != player.inventoryMenu) { // fire INVENTORY_CLOSE if one already open @@ -190,7 +190,7 @@ index 86bddb9c39d8487f050d126dbb479315cb8a2818..8d86649579cb7eb90e3866ed81f2ba4f } CraftServer server = player.level().getCraftServer(); -@@ -1451,8 +1451,18 @@ public class CraftEventFactory { +@@ -1455,8 +1455,18 @@ public class CraftEventFactory { return event; } diff --git a/patches/server/0218-Vanished-players-don-t-have-rights.patch b/patches/server/0218-Vanished-players-don-t-have-rights.patch index bad792a73bbf..fc55caf3e7c1 100644 --- a/patches/server/0218-Vanished-players-don-t-have-rights.patch +++ b/patches/server/0218-Vanished-players-don-t-have-rights.patch @@ -89,10 +89,10 @@ index 16c244f56813479b2e51f1d883ff739949fc86e3..c0b0a9328faf93b85ceaf6cc9989f1a5 public boolean isClientSide() { return this.isClientSide; diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 8d86649579cb7eb90e3866ed81f2ba4f342f8b1c..635982e7c9bb650f72a987e2f866d6f91b75efcf 100644 +index 836eba2f7b4260e5f882b202ef5923bb9bcfcd58..1d2e9f3e5e232faca8de4760d3574fae6200b2b2 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1301,6 +1301,14 @@ public class CraftEventFactory { +@@ -1305,6 +1305,14 @@ public class CraftEventFactory { Projectile projectile = (Projectile) entity.getBukkitEntity(); org.bukkit.entity.Entity collided = position.getEntity().getBukkitEntity(); com.destroystokyo.paper.event.entity.ProjectileCollideEvent event = new com.destroystokyo.paper.event.entity.ProjectileCollideEvent(projectile, collided); diff --git a/patches/server/0239-Add-More-Creeper-API.patch b/patches/server/0239-Add-More-Creeper-API.patch index 9f68dfd41a97..931f2b615897 100644 --- a/patches/server/0239-Add-More-Creeper-API.patch +++ b/patches/server/0239-Add-More-Creeper-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add More Creeper API diff --git a/src/main/java/net/minecraft/world/entity/monster/Creeper.java b/src/main/java/net/minecraft/world/entity/monster/Creeper.java -index c3f59f4a2190327340df71c1283be490557a0a58..2c01fbea62812f795111060d260f871cdf85e8bf 100644 +index 95df4ac539ec284654c53d39955870a46478c27d..9bf11a8b44e696b6587bc775904a836d390e437b 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Creeper.java +++ b/src/main/java/net/minecraft/world/entity/monster/Creeper.java @@ -134,7 +134,7 @@ public class Creeper extends Monster implements PowerableMob { @@ -38,10 +38,10 @@ index c3f59f4a2190327340df71c1283be490557a0a58..2c01fbea62812f795111060d260f871c public boolean canDropMobsSkull() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -index 127e65c5780c6727fde1ea3e597b116a475a666a..4191845bfe05d8691e50143c42090566522f7e74 100644 +index 15bd44f8bd08b55b4da7fbbfdddc7ec3db454d89..42dd26b9170f7d217d73f725a6b8440b45ac2190 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java -@@ -88,4 +88,16 @@ public class CraftCreeper extends CraftMonster implements Creeper { +@@ -101,4 +101,16 @@ public class CraftCreeper extends CraftMonster implements Creeper { public String toString() { return "CraftCreeper"; } diff --git a/patches/server/0242-Add-ray-tracing-methods-to-LivingEntity.patch b/patches/server/0242-Add-ray-tracing-methods-to-LivingEntity.patch index 156b2c1079c3..f490695366d4 100644 --- a/patches/server/0242-Add-ray-tracing-methods-to-LivingEntity.patch +++ b/patches/server/0242-Add-ray-tracing-methods-to-LivingEntity.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add ray tracing methods to LivingEntity diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index ebd81b34d1fbb31ce0f9c92593154fdb6b62bf52..4bf729db65070ac34f7dd84cf16a9475db2ff7c0 100644 +index bf1b8ee85551ff1989369268edf8012758b86fd7..f7a77b31dc196823510f96bd3b2344058e20feac 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3949,6 +3949,19 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3977,6 +3977,19 @@ public abstract class LivingEntity extends Entity implements Attackable { } // Paper start - Make shield blocking delay configurable diff --git a/patches/server/0243-Expose-attack-cooldown-methods-for-Player.patch b/patches/server/0243-Expose-attack-cooldown-methods-for-Player.patch index 36c48b1dd17e..aa32d93194bd 100644 --- a/patches/server/0243-Expose-attack-cooldown-methods-for-Player.patch +++ b/patches/server/0243-Expose-attack-cooldown-methods-for-Player.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose attack cooldown methods for Player diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 38bc1747d2010b9233c64de81eb1c042bd1357b5..c0b92358c03d1724e8c134563f9ca98e69081c6a 100644 +index 62c9f17fc4eeb5d26bfbeabad53016d959198393..e55a8171ba65e1ca499ba3c6aaab9a63702fc298 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2979,6 +2979,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2980,6 +2980,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return this.adventure$pointers; } diff --git a/patches/server/0244-Improve-death-events.patch b/patches/server/0244-Improve-death-events.patch index b4abf99a983b..b4d51a0bb0e8 100644 --- a/patches/server/0244-Improve-death-events.patch +++ b/patches/server/0244-Improve-death-events.patch @@ -19,7 +19,7 @@ public net.minecraft.world.entity.LivingEntity getDeathSound()Lnet/minecraft/sou public net.minecraft.world.entity.LivingEntity getSoundVolume()F diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 622f890d2613acf948b68d6febe0834ceec23c80..5bf3f2faac0af6bddfd2ecb423a13cdf0dd1af1b 100644 +index 7c00c4244233cee313127c1e8c06ef9288d5b9b1..91cc0488c37f60035d99aa310d99d5b8377dbafe 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -268,6 +268,10 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @@ -80,7 +80,7 @@ index 622f890d2613acf948b68d6febe0834ceec23c80..5bf3f2faac0af6bddfd2ecb423a13cdf } } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 4bf729db65070ac34f7dd84cf16a9475db2ff7c0..2c426a68f72b1ed234529b02d2e1d2c18563414b 100644 +index f7a77b31dc196823510f96bd3b2344058e20feac..279fa00fd9043e1995f22c79f47d0b41c27bd933 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -283,6 +283,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -91,7 +91,7 @@ index 4bf729db65070ac34f7dd84cf16a9475db2ff7c0..2c426a68f72b1ed234529b02d2e1d2c1 @Override public float getBukkitYaw() { -@@ -1526,11 +1527,12 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1537,11 +1538,12 @@ public abstract class LivingEntity extends Entity implements Attackable { if (this.isDeadOrDying()) { if (!this.checkTotemDeathProtection(source)) { @@ -107,7 +107,7 @@ index 4bf729db65070ac34f7dd84cf16a9475db2ff7c0..2c426a68f72b1ed234529b02d2e1d2c1 } } else if (flag1) { this.playHurtSound(source); -@@ -1689,6 +1691,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1700,6 +1702,7 @@ public abstract class LivingEntity extends Entity implements Attackable { Entity entity = damageSource.getEntity(); LivingEntity entityliving = this.getKillCredit(); @@ -115,7 +115,7 @@ index 4bf729db65070ac34f7dd84cf16a9475db2ff7c0..2c426a68f72b1ed234529b02d2e1d2c1 if (this.deathScore >= 0 && entityliving != null) { entityliving.awardKillScore(this, this.deathScore, damageSource); } -@@ -1700,24 +1703,59 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1711,24 +1714,59 @@ public abstract class LivingEntity extends Entity implements Attackable { if (!this.level().isClientSide && this.hasCustomName()) { if (org.spigotmc.SpigotConfig.logNamedDeaths) LivingEntity.LOGGER.info("Named entity {} died: {}", this, this.getCombatTracker().getDeathMessage().getString()); // Spigot } @@ -179,7 +179,7 @@ index 4bf729db65070ac34f7dd84cf16a9475db2ff7c0..2c426a68f72b1ed234529b02d2e1d2c1 } } -@@ -1725,7 +1763,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1736,7 +1774,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (!this.level().isClientSide) { boolean flag = false; @@ -188,7 +188,7 @@ index 4bf729db65070ac34f7dd84cf16a9475db2ff7c0..2c426a68f72b1ed234529b02d2e1d2c1 if (this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { BlockPos blockposition = this.blockPosition(); BlockState iblockdata = Blocks.WITHER_ROSE.defaultBlockState(); -@@ -1754,24 +1792,37 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1765,24 +1803,37 @@ public abstract class LivingEntity extends Entity implements Attackable { } } @@ -423,10 +423,10 @@ index ee3902cbada46ffb78c42dbf6f00c859546c76e1..92bb0c63330ad3a4cb13b2dc65502071 // CraftBukkit end this.gameEvent(GameEvent.ENTITY_DIE); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c0b92358c03d1724e8c134563f9ca98e69081c6a..a33fc9288165ec013cef6b90d72871f0058c0857 100644 +index e55a8171ba65e1ca499ba3c6aaab9a63702fc298..ebb465cbc60d09d0087d2545ebd3b455bf5216de 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2516,7 +2516,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2517,7 +2517,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void sendHealthUpdate() { FoodData foodData = this.getHandle().getFoodData(); @@ -443,10 +443,10 @@ index c0b92358c03d1724e8c134563f9ca98e69081c6a..a33fc9288165ec013cef6b90d72871f0 public void injectScaledMaxHealth(Collection collection, boolean force) { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 635982e7c9bb650f72a987e2f866d6f91b75efcf..5254a97f94d24717bdbba1768fffc3d8d292f0fe 100644 +index 1d2e9f3e5e232faca8de4760d3574fae6200b2b2..e7ba5b503e821d18467c2300f780ef37f996b34d 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -893,9 +893,16 @@ public class CraftEventFactory { +@@ -894,9 +894,16 @@ public class CraftEventFactory { CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource); EntityDeathEvent event = new EntityDeathEvent(entity, bukkitDamageSource, drops, victim.getExpReward(damageSource.getEntity())); @@ -463,12 +463,11 @@ index 635982e7c9bb650f72a987e2f866d6f91b75efcf..5254a97f94d24717bdbba1768fffc3d8 victim.expToDrop = event.getDroppedExp(); for (org.bukkit.inventory.ItemStack stack : event.getDrops()) { -@@ -913,8 +920,15 @@ public class CraftEventFactory { +@@ -914,7 +921,14 @@ public class CraftEventFactory { PlayerDeathEvent event = new PlayerDeathEvent(entity, bukkitDamageSource, drops, victim.getExpReward(damageSource.getEntity()), 0, deathMessage); event.setKeepInventory(keepInventory); event.setKeepLevel(victim.keepLevel); // SPIGOT-2222: pre-set keepLevel + populateFields(victim, event); // Paper - make cancellable - org.bukkit.World world = entity.getWorld(); Bukkit.getServer().getPluginManager().callEvent(event); + // Paper start - make cancellable + if (event.isCancelled()) { diff --git a/patches/server/0254-Add-LivingEntity-getTargetEntity.patch b/patches/server/0254-Add-LivingEntity-getTargetEntity.patch index d1ac37709095..f75a1b66aa47 100644 --- a/patches/server/0254-Add-LivingEntity-getTargetEntity.patch +++ b/patches/server/0254-Add-LivingEntity-getTargetEntity.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add LivingEntity#getTargetEntity diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 2c426a68f72b1ed234529b02d2e1d2c18563414b..314fcbeffe3b0adcfbd59b744001b520d6d64a0c 100644 +index 279fa00fd9043e1995f22c79f47d0b41c27bd933..43eddcd8496ff2f089119f6632acfe1b56466c3d 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -127,6 +127,7 @@ import net.minecraft.world.level.storage.loot.LootTable; @@ -16,7 +16,7 @@ index 2c426a68f72b1ed234529b02d2e1d2c18563414b..314fcbeffe3b0adcfbd59b744001b520 import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; -@@ -4013,6 +4014,38 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -4041,6 +4042,38 @@ public abstract class LivingEntity extends Entity implements Attackable { return this.level().clip(raytrace); } diff --git a/patches/server/0261-Reset-players-airTicks-on-respawn.patch b/patches/server/0261-Reset-players-airTicks-on-respawn.patch index 4a7eda111a58..c7bda44c4825 100644 --- a/patches/server/0261-Reset-players-airTicks-on-respawn.patch +++ b/patches/server/0261-Reset-players-airTicks-on-respawn.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Reset players airTicks on respawn diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 2fd93f715bd69fb0217939c87f7872720a9adb7c..b4240bdd2d2baf91f52458602e0063f746dcfb6d 100644 +index 099e740df4966be29a52ea1398bfc7f531d4fb9d..1056286007e1c16c6fce3df7918a082a545f92b5 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2699,6 +2699,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { +@@ -2706,6 +2706,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { this.setHealth(this.getMaxHealth()); this.stopUsingItem(); // CraftBukkit - SPIGOT-6682: Clear active item on reset diff --git a/patches/server/0269-force-entity-dismount-during-teleportation.patch b/patches/server/0269-force-entity-dismount-during-teleportation.patch index 3889b960f36f..4c2464296c9a 100644 --- a/patches/server/0269-force-entity-dismount-during-teleportation.patch +++ b/patches/server/0269-force-entity-dismount-during-teleportation.patch @@ -20,10 +20,10 @@ this is going to be the best soultion all around. Improvements/suggestions welcome! diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index b4240bdd2d2baf91f52458602e0063f746dcfb6d..39504d27b8e0bae74c41e89ebabced1c25d30a7b 100644 +index 1056286007e1c16c6fce3df7918a082a545f92b5..8f3980afc38caf2eda927440957f3e0bb0f2ef66 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2518,9 +2518,15 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { +@@ -2525,9 +2525,15 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @Override public void stopRiding() { @@ -106,10 +106,10 @@ index 131eda47e7a9f90a4057607870acbcb8fecfbf0b..2e376b0b2bf2d49ad0669b6e6fd28762 if (this.valid) { Bukkit.getPluginManager().callEvent(event); diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 314fcbeffe3b0adcfbd59b744001b520d6d64a0c..1ac5e457257748261088f582ed26b94e0e18eced 100644 +index 43eddcd8496ff2f089119f6632acfe1b56466c3d..e047911c7faa3cdcd3df8899857fcadf3eec3d89 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3591,9 +3591,15 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3619,9 +3619,15 @@ public abstract class LivingEntity extends Entity implements Attackable { @Override public void stopRiding() { @@ -146,10 +146,10 @@ index 882236c8ebad90ed2adc873de4dda3b7f3f869d9..632b74e84d6ee58da8806e30b75e16fb this.clientOldAttachPosition = this.blockPosition(); } diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index e60da80cbc2d2dbb98287470e1741fa2a3f95335..e7fc0f6d1a50e82c4c9fc75ca9190f63c5964f3b 100644 +index b70fbc1a93271bbf28402afbe9c6e538a4b6e9aa..fa906334a1c569748d3f2dc073ec03a85bd09d3b 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1160,7 +1160,13 @@ public abstract class Player extends LivingEntity { +@@ -1161,7 +1161,13 @@ public abstract class Player extends LivingEntity { @Override public void removeVehicle() { diff --git a/patches/server/0273-Replace-OfflinePlayer-getLastPlayed.patch b/patches/server/0273-Replace-OfflinePlayer-getLastPlayed.patch index dc94c698a39e..e3974e72e1c3 100644 --- a/patches/server/0273-Replace-OfflinePlayer-getLastPlayed.patch +++ b/patches/server/0273-Replace-OfflinePlayer-getLastPlayed.patch @@ -16,7 +16,7 @@ intent to remove) and replace it with two new methods, clearly named and documented as to their purpose. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 39504d27b8e0bae74c41e89ebabced1c25d30a7b..c75fed2aafc91fbfaed91f5337a5189a1dbb5341 100644 +index 8f3980afc38caf2eda927440957f3e0bb0f2ef66..4e8ef3dfde97f40d2c2163e2e811b2ae77bae14e 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -268,6 +268,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @@ -106,7 +106,7 @@ index 461656e1cb095243bfe7a9ee2906e5b00574ae78..411b280ac3e27e72091db813c0c9b69b public Location getLastDeathLocation() { if (this.getData().contains("LastDeathLocation", 10)) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index a33fc9288165ec013cef6b90d72871f0058c0857..d649fd886faf0d4d989362c4ef0e9c50247c280f 100644 +index ebb465cbc60d09d0087d2545ebd3b455bf5216de..3ca09d5eb1e97cbd11cab34aa8600b2c92237517 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -210,6 +210,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -117,7 +117,7 @@ index a33fc9288165ec013cef6b90d72871f0058c0857..d649fd886faf0d4d989362c4ef0e9c50 public CraftPlayer(CraftServer server, ServerPlayer entity) { super(server, entity); -@@ -2048,6 +2049,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2049,6 +2050,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.firstPlayed = firstPlayed; } @@ -136,7 +136,7 @@ index a33fc9288165ec013cef6b90d72871f0058c0857..d649fd886faf0d4d989362c4ef0e9c50 public void readExtraData(CompoundTag nbttagcompound) { this.hasPlayedBefore = true; if (nbttagcompound.contains("bukkit")) { -@@ -2070,6 +2083,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2071,6 +2084,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } public void setExtraData(CompoundTag nbttagcompound) { @@ -145,7 +145,7 @@ index a33fc9288165ec013cef6b90d72871f0058c0857..d649fd886faf0d4d989362c4ef0e9c50 if (!nbttagcompound.contains("bukkit")) { nbttagcompound.put("bukkit", new CompoundTag()); } -@@ -2084,6 +2099,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2085,6 +2100,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { data.putLong("firstPlayed", this.getFirstPlayed()); data.putLong("lastPlayed", System.currentTimeMillis()); data.putString("lastKnownName", handle.getScoreboardName()); diff --git a/patches/server/0289-Mob-Spawner-API-Enhancements.patch b/patches/server/0289-Mob-Spawner-API-Enhancements.patch index dc419af69220..1f15425c9cac 100644 --- a/patches/server/0289-Mob-Spawner-API-Enhancements.patch +++ b/patches/server/0289-Mob-Spawner-API-Enhancements.patch @@ -69,43 +69,150 @@ index 1d0964a7f544735a0213d5c7832c71f53db139a9..b90127f9f805fdb5bb43a4b8ad2b1049 nbt.putShort("MaxNearbyEntities", (short) this.maxNearbyEntities); nbt.putShort("RequiredPlayerRange", (short) this.requiredPlayerRange); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -index 33718f8861b46452ef9977ac0cbd7624a86edb30..4659f11c3aadda2617951f9d98b4858efe1400d7 100644 +index 9b2b6697d0b64da2bc99dc646f552c2689d5a1fc..146dde200845abcbe11015dda2c826a1aa711e42 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCreatureSpawner.java -@@ -256,4 +256,36 @@ public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner { ++public class CraftCreatureSpawner extends CraftBlockEntityState implements CreatureSpawner, org.bukkit.craftbukkit.spawner.PaperSharedSpawnerLogic { // Paper - more spawner API + + public CraftCreatureSpawner(World world, SpawnerBlockEntity tileEntity) { + super(world, tileEntity); +@@ -291,4 +291,38 @@ public class CraftCreatureSpawner extends CraftBlockEntityState(nms.slotDropChances().entrySet().stream().collect(Collectors.toMap((entry) -> CraftEquipmentSlot.getSlot(entry.getKey()), Map.Entry::getValue))) )).orElse(null); } + -+ // Paper start ++ // Paper start - more spawner API + @Override + public boolean isActivated() { -+ this.requirePlaced(); -+ return this.getSnapshot().getSpawner().isNearPlayer(this.world.getHandle(), this.getPosition()); ++ requirePlaced(); ++ return org.bukkit.craftbukkit.spawner.PaperSharedSpawnerLogic.super.isActivated(); + } + + @Override + public void resetTimer() { -+ this.requirePlaced(); -+ this.getSnapshot().getSpawner().delay(this.world.getHandle(), this.getPosition()); ++ requirePlaced(); ++ org.bukkit.craftbukkit.spawner.PaperSharedSpawnerLogic.super.resetTimer(); ++ } ++ ++ @Override ++ public void setNextSpawnData(final SpawnData spawnData) { ++ this.getSpawner().setNextSpawnData(this.isPlaced() ? this.getInternalWorld() : null, this.getInternalPosition(), spawnData); ++ } ++ ++ @Override ++ public BaseSpawner getSpawner() { ++ return this.getSnapshot().getSpawner(); ++ } ++ ++ @Override ++ public net.minecraft.core.BlockPos getInternalPosition() { ++ return this.getPosition(); ++ } ++ ++ @Override ++ public net.minecraft.world.level.Level getInternalWorld() { ++ return this.world.getHandle(); ++ } ++ // Paper end - more spawner API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java +index 72e34dbfadcebb26a0707ce095b0d270f4d1d97c..66cf668183cfdb36f567729a40d01d996ed507e1 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java +@@ -16,7 +16,7 @@ import org.bukkit.entity.EntitySnapshot; + import org.bukkit.entity.EntityType; + import org.bukkit.entity.minecart.SpawnerMinecart; + +-final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMinecart { ++final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMinecart, org.bukkit.craftbukkit.spawner.PaperSharedSpawnerLogic { + CraftMinecartMobSpawner(CraftServer server, MinecartSpawner entity) { + super(server, entity); + } +@@ -171,4 +171,21 @@ final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMine + public String toString() { + return "CraftMinecartMobSpawner"; + } ++ ++ // Paper start - more spawner API ++ @Override ++ public net.minecraft.world.level.BaseSpawner getSpawner() { ++ return this.getHandle().getSpawner(); + } + + @Override -+ public void setSpawnedItem(org.bukkit.inventory.ItemStack itemStack) { ++ public net.minecraft.world.level.Level getInternalWorld() { ++ return this.getHandle().level(); ++ } ++ ++ @Override ++ public net.minecraft.core.BlockPos getInternalPosition() { ++ return this.getHandle().blockPosition(); ++ } ++ // Paper end - more spawner API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/spawner/PaperSharedSpawnerLogic.java b/src/main/java/org/bukkit/craftbukkit/spawner/PaperSharedSpawnerLogic.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e01bf4afb04ae66dee8c194743709aa6ac0e4633 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/spawner/PaperSharedSpawnerLogic.java +@@ -0,0 +1,55 @@ ++package org.bukkit.craftbukkit.spawner; ++ ++import com.google.common.base.Preconditions; ++import java.util.Optional; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.level.BaseSpawner; ++import net.minecraft.world.level.Level; ++import net.minecraft.world.level.SpawnData; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.inventory.ItemStack; ++import org.bukkit.spawner.Spawner; ++ ++/** ++ * A common parent interface for both the {@link org.bukkit.craftbukkit.block.CraftCreatureSpawner} and minecart mob spawner. ++ */ ++public interface PaperSharedSpawnerLogic extends Spawner { ++ ++ BaseSpawner getSpawner(); ++ ++ Level getInternalWorld(); ++ ++ BlockPos getInternalPosition(); ++ ++ default boolean isActivated() { ++ return this.getSpawner().isNearPlayer(this.getInternalWorld(), this.getInternalPosition()); ++ } ++ ++ default void resetTimer() { ++ this.getSpawner().delay(this.getInternalWorld(), this.getInternalPosition()); ++ } ++ ++ default void setNextSpawnData(SpawnData spawnData) { ++ this.getSpawner().setNextSpawnData(this.getInternalWorld(), this.getInternalPosition(), spawnData); ++ } ++ ++ default void setSpawnedItem(final ItemStack itemStack) { + Preconditions.checkArgument(itemStack != null && !itemStack.getType().isAir(), "spawners cannot spawn air"); -+ net.minecraft.world.item.ItemStack item = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(itemStack); -+ net.minecraft.nbt.CompoundTag entity = new net.minecraft.nbt.CompoundTag(); -+ entity.putString("id", net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.getKey(net.minecraft.world.entity.EntityType.ITEM).toString()); -+ entity.put("Item", item.save(this.world.getHandle().registryAccess())); -+ this.getSnapshot().getSpawner().setNextSpawnData( -+ this.isPlaced() ? this.world.getHandle() : null, -+ this.getPosition(), ++ ++ final net.minecraft.world.item.ItemStack item = CraftItemStack.asNMSCopy(itemStack); ++ final CompoundTag entity = new CompoundTag(); ++ entity.putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(EntityType.ITEM).toString()); ++ entity.put("Item", item.save(this.getInternalWorld().registryAccess())); ++ ++ this.setNextSpawnData( + new net.minecraft.world.level.SpawnData( + entity, + java.util.Optional.empty(), -+ Optional.ofNullable(this.getSnapshot().getSpawner().nextSpawnData).flatMap(SpawnData::equipment) ++ Optional.ofNullable(this.getSpawner().nextSpawnData).flatMap(SpawnData::equipment) + ) + ); + } -+ // Paper end - } ++} diff --git a/patches/server/0298-Prevent-consuming-the-wrong-itemstack.patch b/patches/server/0298-Prevent-consuming-the-wrong-itemstack.patch index de0a5f77d5f9..cb2edff807dc 100644 --- a/patches/server/0298-Prevent-consuming-the-wrong-itemstack.patch +++ b/patches/server/0298-Prevent-consuming-the-wrong-itemstack.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Prevent consuming the wrong itemstack diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 1ac5e457257748261088f582ed26b94e0e18eced..94492da51fe2a6343ab3c41d26ca2a195e14bc62 100644 +index e047911c7faa3cdcd3df8899857fcadf3eec3d89..f13fb8d408e02e3c561e8f2b9c823c13033b4f94 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3827,9 +3827,14 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3855,9 +3855,14 @@ public abstract class LivingEntity extends Entity implements Attackable { } public void startUsingItem(InteractionHand hand) { @@ -24,7 +24,7 @@ index 1ac5e457257748261088f582ed26b94e0e18eced..94492da51fe2a6343ab3c41d26ca2a19 this.useItem = itemstack; this.useItemRemaining = itemstack.getUseDuration(this); if (!this.level().isClientSide) { -@@ -3914,6 +3919,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3942,6 +3947,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.releaseUsingItem(); } else { if (!this.useItem.isEmpty() && this.isUsingItem()) { @@ -32,7 +32,7 @@ index 1ac5e457257748261088f582ed26b94e0e18eced..94492da51fe2a6343ab3c41d26ca2a19 this.triggerItemUseEffects(this.useItem, 16); // CraftBukkit start - fire PlayerItemConsumeEvent ItemStack itemstack; -@@ -3948,8 +3954,8 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3976,8 +3982,8 @@ public abstract class LivingEntity extends Entity implements Attackable { } this.stopUsingItem(); diff --git a/patches/server/0319-Entity-Jump-API.patch b/patches/server/0319-Entity-Jump-API.patch index 9d3bf218cf88..20e546b1d6a2 100644 --- a/patches/server/0319-Entity-Jump-API.patch +++ b/patches/server/0319-Entity-Jump-API.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Entity Jump API public net.minecraft.world.entity.LivingEntity jumping diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 94492da51fe2a6343ab3c41d26ca2a195e14bc62..9d924c48dedf9a61f555bf7c9d658e925169ccd2 100644 +index f13fb8d408e02e3c561e8f2b9c823c13033b4f94..f4ba1c72ec470cc79e40d7427e08185d5944d373 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3405,8 +3405,10 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3433,8 +3433,10 @@ public abstract class LivingEntity extends Entity implements Attackable { } else if (this.isInLava() && (!this.onGround() || d3 > d4)) { this.jumpInLiquid(FluidTags.LAVA); } else if ((this.onGround() || flag && d3 <= d4) && this.noJumpDelay == 0) { diff --git a/patches/server/0322-add-hand-to-BlockMultiPlaceEvent.patch b/patches/server/0322-add-hand-to-BlockMultiPlaceEvent.patch index 3a4d8cf5a787..3247f38cb940 100644 --- a/patches/server/0322-add-hand-to-BlockMultiPlaceEvent.patch +++ b/patches/server/0322-add-hand-to-BlockMultiPlaceEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] add hand to BlockMultiPlaceEvent diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 5254a97f94d24717bdbba1768fffc3d8d292f0fe..6e9f0fdbfffe7a08185a125e2ad0f2227d25cc07 100644 +index e7ba5b503e821d18467c2300f780ef37f996b34d..f670ddd3633bf36b653bdf994f459e84e09bfbff 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -402,13 +402,18 @@ public class CraftEventFactory { +@@ -403,13 +403,18 @@ public class CraftEventFactory { } org.bukkit.inventory.ItemStack item; diff --git a/patches/server/0330-Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/0330-Add-Raw-Byte-ItemStack-Serialization.patch index 5862ff1c75b4..800948f497c2 100644 --- a/patches/server/0330-Add-Raw-Byte-ItemStack-Serialization.patch +++ b/patches/server/0330-Add-Raw-Byte-ItemStack-Serialization.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add Raw Byte ItemStack Serialization Serializes using NBT which is safer for server data migrations than bukkits format. diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 7800e0a5aa381181d6a19d55f90490154de05c04..890beb473c240c084c4dd12c5dd792895117358e 100644 +index e85faddc157869824e30426a7ca2c577552aea9c..03a72e19e060cdb0dd8fcf52742da27dcfcd1356 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -483,6 +483,53 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -469,6 +469,53 @@ public final class CraftMagicNumbers implements UnsafeValues { public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { return new com.destroystokyo.paper.PaperVersionFetcher(); } diff --git a/patches/server/0336-Dead-Player-s-shouldn-t-be-able-to-move.patch b/patches/server/0336-Dead-Player-s-shouldn-t-be-able-to-move.patch index 6666c9a721a6..d10a5a50c4a5 100644 --- a/patches/server/0336-Dead-Player-s-shouldn-t-be-able-to-move.patch +++ b/patches/server/0336-Dead-Player-s-shouldn-t-be-able-to-move.patch @@ -7,10 +7,10 @@ This fixes a lot of game state issues where packets were delayed for processing due to 1.15's new queue but processed while dead. diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index e7fc0f6d1a50e82c4c9fc75ca9190f63c5964f3b..acb2ccc8a940ea0ccd3d1f6d69c926d513f42872 100644 +index fa906334a1c569748d3f2dc073ec03a85bd09d3b..cb89b020d93ac838843ec2cbad562326a1e4257b 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1172,7 +1172,7 @@ public abstract class Player extends LivingEntity { +@@ -1173,7 +1173,7 @@ public abstract class Player extends LivingEntity { @Override protected boolean isImmobile() { diff --git a/patches/server/0341-Prevent-opening-inventories-when-frozen.patch b/patches/server/0341-Prevent-opening-inventories-when-frozen.patch index db9bb38d46e4..5969f96e5143 100644 --- a/patches/server/0341-Prevent-opening-inventories-when-frozen.patch +++ b/patches/server/0341-Prevent-opening-inventories-when-frozen.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Prevent opening inventories when frozen diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 8dff4fb382639e4db9c80bbdfbc69167aa7996a1..1e780b73fac4d686444ff3a009cf33318068d8d1 100644 +index fb72ce049aeb49ee59cd07e074e61bb31591c252..b4089878f7f8cd32cea7741b72be5bb5218f3032 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -712,7 +712,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @@ -27,7 +27,7 @@ index 8dff4fb382639e4db9c80bbdfbc69167aa7996a1..1e780b73fac4d686444ff3a009cf3331 this.initMenu(container); return OptionalInt.of(this.containerCounter); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index c79607a2f45b7a487a95cf98b9b0eb6b36501410..eb2d39d408e7f46a8f047a2b0d76981f24e1320a 100644 +index 703bb1bb42b1668c04824489fd2f349052025979..b55919a0e61a36697c95599dba17dbe2b788fd2a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -326,7 +326,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -39,7 +39,7 @@ index c79607a2f45b7a487a95cf98b9b0eb6b36501410..eb2d39d408e7f46a8f047a2b0d76981f player.containerMenu = container; player.initMenu(container); } -@@ -400,7 +400,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -401,7 +401,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper //player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment diff --git a/patches/server/0342-Don-t-run-entity-collision-code-if-not-needed.patch b/patches/server/0342-Don-t-run-entity-collision-code-if-not-needed.patch index 6495c29c3045..ce9cc70a02b5 100644 --- a/patches/server/0342-Don-t-run-entity-collision-code-if-not-needed.patch +++ b/patches/server/0342-Don-t-run-entity-collision-code-if-not-needed.patch @@ -12,10 +12,10 @@ The entity's current team collision rule causes them to NEVER collide. Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 9d924c48dedf9a61f555bf7c9d658e925169ccd2..24ec68cecd11b8faa8bff11989b64985c26707cc 100644 +index f4ba1c72ec470cc79e40d7427e08185d5944d373..57528fce99102da6b3d0c3d9dbf9d2cd71375ff8 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3516,10 +3516,24 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3544,10 +3544,24 @@ public abstract class LivingEntity extends Entity implements Attackable { if (this.level().isClientSide()) { this.level().getEntities(EntityTypeTest.forClass(net.minecraft.world.entity.player.Player.class), this.getBoundingBox(), EntitySelector.pushableBy(this)).forEach(this::doPush); } else { diff --git a/patches/server/0347-Add-PlayerAttackEntityCooldownResetEvent.patch b/patches/server/0347-Add-PlayerAttackEntityCooldownResetEvent.patch index 90c43e9e4df0..be9e57b2e3f4 100644 --- a/patches/server/0347-Add-PlayerAttackEntityCooldownResetEvent.patch +++ b/patches/server/0347-Add-PlayerAttackEntityCooldownResetEvent.patch @@ -5,15 +5,16 @@ Subject: [PATCH] Add PlayerAttackEntityCooldownResetEvent diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 24ec68cecd11b8faa8bff11989b64985c26707cc..045cfadc67c597f4607ed3ba6a5c9b06e95814ba 100644 +index 57528fce99102da6b3d0c3d9dbf9d2cd71375ff8..f2e66b50b32d197f9a8d4a9672ebf1413e66d59b 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2248,7 +2248,16 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2277,7 +2277,17 @@ public abstract class LivingEntity extends Entity implements Attackable { + } - EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); if (damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player) { - ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired + // Paper start - PlayerAttackEntityCooldownResetEvent ++ //((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); // Moved from EntityHuman in order to make the cooldown reset get called after the damage event is fired + if (damagesource.getEntity() instanceof ServerPlayer) { + ServerPlayer player = (ServerPlayer) damagesource.getEntity(); + if (new com.destroystokyo.paper.event.player.PlayerAttackEntityCooldownResetEvent(player.getBukkitEntity(), this.getBukkitEntity(), player.getAttackStrengthScale(0F)).callEvent()) { @@ -24,5 +25,5 @@ index 24ec68cecd11b8faa8bff11989b64985c26707cc..045cfadc67c597f4607ed3ba6a5c9b06 + } + // Paper end - PlayerAttackEntityCooldownResetEvent } - if (event.isCancelled()) { - return false; + + // Resistance diff --git a/patches/server/0350-Fix-item-duplication-and-teleport-issues.patch b/patches/server/0350-Fix-item-duplication-and-teleport-issues.patch index c3d180d8c149..5c2cede8f5bf 100644 --- a/patches/server/0350-Fix-item-duplication-and-teleport-issues.patch +++ b/patches/server/0350-Fix-item-duplication-and-teleport-issues.patch @@ -69,10 +69,10 @@ index 61ae5553a22adc84acbe2962632b8f564ed80d88..2c21ef3f9096d1282091a7ec34e57fd7 public float getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState, float max) { diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 045cfadc67c597f4607ed3ba6a5c9b06e95814ba..2fb30b4841cbbbe388c28477e13d882446ff73e7 100644 +index f2e66b50b32d197f9a8d4a9672ebf1413e66d59b..fe73a6728de0fad50451d3090002b6c0421d4c43 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1717,9 +1717,9 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1728,9 +1728,9 @@ public abstract class LivingEntity extends Entity implements Attackable { // Paper start org.bukkit.event.entity.EntityDeathEvent deathEvent = this.dropAllDeathLoot(worldserver, damageSource); if (deathEvent == null || !deathEvent.isCancelled()) { @@ -85,7 +85,7 @@ index 045cfadc67c597f4607ed3ba6a5c9b06e95814ba..2fb30b4841cbbbe388c28477e13d8824 // Paper start - clear equipment if event is not cancelled if (this instanceof Mob) { for (EquipmentSlot slot : this.clearedEquipmentSlots) { -@@ -1811,8 +1811,13 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1822,8 +1822,13 @@ public abstract class LivingEntity extends Entity implements Attackable { this.dropCustomDeathLoot(world, damageSource, flag); this.clearEquipmentSlots = prev; // Paper } @@ -124,10 +124,10 @@ index 92bb0c63330ad3a4cb13b2dc655020714e9b1ffd..cc1189c2d7dc57ba8f29aad4ba5d2a07 } } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 6e9f0fdbfffe7a08185a125e2ad0f2227d25cc07..720ea811407b4288b9923cf7db0ac44ad1a086e0 100644 +index f670ddd3633bf36b653bdf994f459e84e09bfbff..01c16286cf210a366decf7046a6a6b94284f9934 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -895,6 +895,11 @@ public class CraftEventFactory { +@@ -896,6 +896,11 @@ public class CraftEventFactory { } public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource, List drops) { @@ -139,7 +139,7 @@ index 6e9f0fdbfffe7a08185a125e2ad0f2227d25cc07..720ea811407b4288b9923cf7db0ac44a CraftLivingEntity entity = (CraftLivingEntity) victim.getBukkitEntity(); CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource); EntityDeathEvent event = new EntityDeathEvent(entity, bukkitDamageSource, drops, victim.getExpReward(damageSource.getEntity())); -@@ -909,11 +914,13 @@ public class CraftEventFactory { +@@ -910,11 +915,13 @@ public class CraftEventFactory { playDeathSound(victim, event); // Paper end victim.expToDrop = event.getDroppedExp(); diff --git a/patches/server/0358-ExperienceOrb-merging-stacking-API-and-fixes.patch b/patches/server/0358-ExperienceOrb-merging-stacking-API-and-fixes.patch index fb7613e2f058..4686e1475ff3 100644 --- a/patches/server/0358-ExperienceOrb-merging-stacking-API-and-fixes.patch +++ b/patches/server/0358-ExperienceOrb-merging-stacking-API-and-fixes.patch @@ -77,10 +77,10 @@ index 5a7d314ec0562e472f5dc45924a7b24841cff126..650e4a01cecc4cc08e7ff9ebcc4c3670 public java.util.UUID getTriggerEntityId() { return getHandle().triggerEntityId; diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 720ea811407b4288b9923cf7db0ac44ad1a086e0..82f7a36e71ed17d44ad0e5be99f8f6fc450d0732 100644 +index 01c16286cf210a366decf7046a6a6b94284f9934..baf282b200a14733cf2148f237d972224d60a266 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -704,15 +704,29 @@ public class CraftEventFactory { +@@ -705,15 +705,29 @@ public class CraftEventFactory { if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) { double radius = world.spigotConfig.expMerge; if (radius > 0) { diff --git a/patches/server/0383-Improve-fix-EntityTargetLivingEntityEvent.patch b/patches/server/0383-Improve-fix-EntityTargetLivingEntityEvent.patch index 513faeb27d9a..e6532342d152 100644 --- a/patches/server/0383-Improve-fix-EntityTargetLivingEntityEvent.patch +++ b/patches/server/0383-Improve-fix-EntityTargetLivingEntityEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Improve/fix EntityTargetLivingEntityEvent diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java b/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java -index 5aeef564cdaabeed88a52635e56073cca3a9d1f1..fe635e46569c67dac1d3581ee930d1bfa8b4030e 100644 +index cc7d161b53a2295fa1745254eafb8a70c7b6c7b2..c4bd46435bef33bb743ef43a19edc0ad6854e256 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java -@@ -47,17 +47,30 @@ public class StopAttackingIfTargetInvalid { +@@ -47,16 +47,30 @@ public class StopAttackingIfTargetInvalid { if (entityinsentient.canAttack(entityliving) && (!shouldForgetIfTargetUnreachable || !StopAttackingIfTargetInvalid.isTiredOfTryingToReachTarget(entityinsentient, behaviorbuilder_b.tryGet(memoryaccessor1))) && entityliving.isAlive() && entityliving.level() == entityinsentient.level() && !alternativeCondition.test(entityliving)) { return true; } else { @@ -33,13 +33,12 @@ index 5aeef564cdaabeed88a52635e56073cca3a9d1f1..fe635e46569c67dac1d3581ee930d1bf if (event.isCancelled()) { return false; } -- if (event.getTarget() == null) { -- memoryaccessor.erase(); +- if (event.getTarget() != null) { +- entityinsentient.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); - return true; - } -- entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); + // if (event.getTarget() == null) { // Paper - this is wrong, you are skipping the forgetCallback -+ // memoryaccessor.erase(); ++ // entityinsentient.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); + // return true; + // } + // entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); diff --git a/patches/server/0385-Add-PrepareResultEvent.patch b/patches/server/0385-Add-PrepareResultEvent.patch index e49f6836383f..962fe955876d 100644 --- a/patches/server/0385-Add-PrepareResultEvent.patch +++ b/patches/server/0385-Add-PrepareResultEvent.patch @@ -94,10 +94,10 @@ index 04d9793a83c724350f74616558f650082f9805d9..bb29107cb15e2ec644a14cabb3cf91f4 private static SingleRecipeInput createRecipeInput(Container inventory) { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 82f7a36e71ed17d44ad0e5be99f8f6fc450d0732..679098ee1e0117c5786ddcf10540f09ae4ca3946 100644 +index baf282b200a14733cf2148f237d972224d60a266..cd3c0f9672aca19e28aa3e04e0060bf250f122ce 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1653,6 +1653,12 @@ public class CraftEventFactory { +@@ -1657,6 +1657,12 @@ public class CraftEventFactory { } public static PrepareAnvilEvent callPrepareAnvilEvent(InventoryView view, ItemStack item) { @@ -110,7 +110,7 @@ index 82f7a36e71ed17d44ad0e5be99f8f6fc450d0732..679098ee1e0117c5786ddcf10540f09a PrepareAnvilEvent event = new PrepareAnvilEvent(view, CraftItemStack.asCraftMirror(item).clone()); event.getView().getPlayer().getServer().getPluginManager().callEvent(event); event.getInventory().setItem(2, event.getResult()); -@@ -1660,6 +1666,12 @@ public class CraftEventFactory { +@@ -1664,6 +1670,12 @@ public class CraftEventFactory { } public static PrepareGrindstoneEvent callPrepareGrindstoneEvent(InventoryView view, ItemStack item) { @@ -123,7 +123,7 @@ index 82f7a36e71ed17d44ad0e5be99f8f6fc450d0732..679098ee1e0117c5786ddcf10540f09a PrepareGrindstoneEvent event = new PrepareGrindstoneEvent(view, CraftItemStack.asCraftMirror(item).clone()); event.getView().getPlayer().getServer().getPluginManager().callEvent(event); event.getInventory().setItem(2, event.getResult()); -@@ -1667,12 +1679,39 @@ public class CraftEventFactory { +@@ -1671,12 +1683,39 @@ public class CraftEventFactory { } public static PrepareSmithingEvent callPrepareSmithingEvent(InventoryView view, ItemStack item) { diff --git a/patches/server/0386-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch b/patches/server/0386-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch index 5be503cd7d24..0603020790e7 100644 --- a/patches/server/0386-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch +++ b/patches/server/0386-Don-t-check-chunk-for-portal-on-world-gen-entity-add.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Don't check chunk for portal on world gen entity add diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 2fb30b4841cbbbe388c28477e13d882446ff73e7..2ca4bb4784e3ef6760e1f2e1eab93cfbc5b27a0f 100644 +index fe73a6728de0fad50451d3090002b6c0421d4c43..ef2240b476cc994618ea002b302b537a5d70c799 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3630,7 +3630,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3659,7 +3659,7 @@ public abstract class LivingEntity extends Entity implements Attackable { Entity entity = this.getVehicle(); super.stopRiding(suppressCancellation); // Paper - Force entity dismount during teleportation diff --git a/patches/server/0395-Brand-support.patch b/patches/server/0395-Brand-support.patch index 0e14f01ddcd9..24c2290fe47e 100644 --- a/patches/server/0395-Brand-support.patch +++ b/patches/server/0395-Brand-support.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Brand support diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 9cba3ac95318f1a4b680b541ce5d825fc5c4ad02..4998643920b8314737832ad15431b794e1aa6df0 100644 +index d4e933b8d0f2352ac035b99fc386e6fe6d7f6651..4e76d4cacf688bce9d00eaff5ea601dbf16493e9 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -294,6 +294,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @@ -57,10 +57,10 @@ index 2d1fad00ee084841618f0da8113c7aac8c0e2b0d..a3c67bdc2c08b3550534f37d15b0db90 } catch (Exception ex) { ServerGamePacketListenerImpl.LOGGER.error("Couldn\'t dispatch custom payload", ex); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 8865dabc729af78fcc306d48e754c54f80dfb2e4..74e40e74f95d366b508d6e746f3ed2710ab0613a 100644 +index aa549021a1676d0aa0aa7c9f1b0bf0bb800385a4..1febe581fbbc3accbf8fdbf086fba427cefdd3e9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -3138,6 +3138,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3139,6 +3139,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { // Paper end }; diff --git a/patches/server/0402-Add-BellRingEvent.patch b/patches/server/0402-Add-BellRingEvent.patch index 9ac85f17e9dc..6b974f5db04f 100644 --- a/patches/server/0402-Add-BellRingEvent.patch +++ b/patches/server/0402-Add-BellRingEvent.patch @@ -7,10 +7,10 @@ Add a new event, BellRingEvent, to trigger whenever a player rings a village bell. Passes along the bell block and the player who rang it. diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 679098ee1e0117c5786ddcf10540f09ae4ca3946..4679e1399288db68ae0325cf62ea1a8fb6d6c80b 100644 +index cd3c0f9672aca19e28aa3e04e0060bf250f122ce..dc7c73f36b7df05ee34e9686c99c44a24acecdcb 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -368,10 +368,11 @@ public class CraftEventFactory { +@@ -369,10 +369,11 @@ public class CraftEventFactory { return tradeSelectEvent; } diff --git a/patches/server/0408-Add-methods-to-get-translation-keys.patch b/patches/server/0408-Add-methods-to-get-translation-keys.patch index 7bc6ab009f84..cae11912b69f 100644 --- a/patches/server/0408-Add-methods-to-get-translation-keys.patch +++ b/patches/server/0408-Add-methods-to-get-translation-keys.patch @@ -42,10 +42,10 @@ index f6ffb81b68e0cf3afebe901a5ba8e305bb94b77a..f2f62667ddf082796011ad7dd025e885 + // Paper end - add Translatable } diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index 97a7dc31fe7a2defed2202ccc518c66b7ff4b0da..3ea6e6678432957c5caaff15ba20f8a8ddb393c9 100644 +index f73017bff613bd62b86c974b29576e241c24c927..fc6606e1bf2e2c35cb6c84af78859c3441775907 100644 --- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -@@ -171,6 +171,11 @@ public class CraftEnchantment extends Enchantment implements Handleable implements ItemType.Typed, Han +@@ -240,4 +240,11 @@ public class CraftItemType implements ItemType.Typed, Han public Material asMaterial() { return Registry.MATERIAL.get(this.key); } @@ -74,7 +74,7 @@ index 47b5a4aeb3e67e7009962c610f8f45a496671b89..3ad2d93fa4b5174531349e9dfce4f489 + // Paper end - add Translatable } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java -index 11960a5433675c25d7ba061be753815746dd0142..f2cecd01f7f214a023e1bdeecc14359f696fb9d4 100644 +index 305eac6845119c36d041bf75930eb0909405911c..8c1d2d0521da52f9a1262f5433da21700b9b0454 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java @@ -110,7 +110,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { diff --git a/patches/server/0412-Add-additional-open-container-api-to-HumanEntity.patch b/patches/server/0412-Add-additional-open-container-api-to-HumanEntity.patch index 47aa453acf0b..be29dd6b1c65 100644 --- a/patches/server/0412-Add-additional-open-container-api-to-HumanEntity.patch +++ b/patches/server/0412-Add-additional-open-container-api-to-HumanEntity.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Add additional open container api to HumanEntity public net/minecraft/world/level/block/state/BlockBehaviour getMenuProvider(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/MenuProvider; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index bbd3f0981eb95348ef12c9af8fa1712c022ed869..9393e9d21fcc41cb0f20b98d9f28c95b0e523f62 100644 +index 084938fa2ffa7ee462766bf03f8e2b4c0fd4bf6b..8f4c4fed41676157b717c20a5ccbfe6ad4bdb3c4 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -462,6 +462,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -463,6 +463,70 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { return this.getHandle().containerMenu.getBukkitView(); } diff --git a/patches/server/0415-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/0415-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch index 1be83ad3359c..31a4396f92ee 100644 --- a/patches/server/0415-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ b/patches/server/0415-Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -21,10 +21,10 @@ index 335962dfe50d8d691a2a1fc6224950641e2b5a2b..203aacc9e116c1335bde1cff4d59674b + // Paper end - Expose entity id counter } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 890beb473c240c084c4dd12c5dd792895117358e..5eeb2a46cb093d21ce7276373a838041be7a47b3 100644 +index 03a72e19e060cdb0dd8fcf52742da27dcfcd1356..94ec28a4f9d12873dff6700a12fb66e29820d3d9 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -530,6 +530,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -516,6 +516,11 @@ public final class CraftMagicNumbers implements UnsafeValues { Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!"); return compound; } diff --git a/patches/server/0431-Fix-client-lag-on-advancement-loading.patch b/patches/server/0431-Fix-client-lag-on-advancement-loading.patch index b21d181e44ba..ded2b5101b71 100644 --- a/patches/server/0431-Fix-client-lag-on-advancement-loading.patch +++ b/patches/server/0431-Fix-client-lag-on-advancement-loading.patch @@ -15,10 +15,10 @@ manually reload the advancement data for all players, which normally takes place as a part of the datapack reloading. diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 5eeb2a46cb093d21ce7276373a838041be7a47b3..50322927460ec9464363617e3f7fe5ff8faa1f6f 100644 +index 94ec28a4f9d12873dff6700a12fb66e29820d3d9..7427a81a779b82f96d34a3de228c9d59ee77fea7 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -337,7 +337,13 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -333,7 +333,13 @@ public final class CraftMagicNumbers implements UnsafeValues { Bukkit.getLogger().log(Level.SEVERE, "Error saving advancement " + key, ex); } diff --git a/patches/server/0437-Fix-Player-spawnParticle-x-y-z-precision-loss.patch b/patches/server/0437-Fix-Player-spawnParticle-x-y-z-precision-loss.patch index bb0bf544685b..83724b282d07 100644 --- a/patches/server/0437-Fix-Player-spawnParticle-x-y-z-precision-loss.patch +++ b/patches/server/0437-Fix-Player-spawnParticle-x-y-z-precision-loss.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix Player spawnParticle x/y/z precision loss diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 74e40e74f95d366b508d6e746f3ed2710ab0613a..803a1d9350276c44eef622436cc4026460436ae7 100644 +index 1febe581fbbc3accbf8fdbf086fba427cefdd3e9..533bb2da5ed226a31f0534f17048afa2d99e36ee 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2706,7 +2706,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2707,7 +2707,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX, double offsetY, double offsetZ, double extra, T data, boolean force) { diff --git a/patches/server/0442-Climbing-should-not-bypass-cramming-gamerule.patch b/patches/server/0442-Climbing-should-not-bypass-cramming-gamerule.patch index 7ee5e8ee65ec..db770d8d7359 100644 --- a/patches/server/0442-Climbing-should-not-bypass-cramming-gamerule.patch +++ b/patches/server/0442-Climbing-should-not-bypass-cramming-gamerule.patch @@ -44,10 +44,10 @@ index ee4495b67c46cf1282cdd6ad15b224b0b7b10bfb..e382a29b441b656f35bc24cb90f95cb4 } else if (entity.level().isClientSide && (!(entity1 instanceof Player) || !((Player) entity1).isLocalPlayer())) { return false; diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 2ca4bb4784e3ef6760e1f2e1eab93cfbc5b27a0f..536625307d7b820bd5293e70274e4d3885b04cba 100644 +index ef2240b476cc994618ea002b302b537a5d70c799..c7ead86c5048381c97d01a09ac8a5a84cd93c5db 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3544,7 +3544,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3573,7 +3573,7 @@ public abstract class LivingEntity extends Entity implements Attackable { return; } // Paper end - don't run getEntities if we're not going to use its result @@ -56,7 +56,7 @@ index 2ca4bb4784e3ef6760e1f2e1eab93cfbc5b27a0f..536625307d7b820bd5293e70274e4d38 if (!list.isEmpty()) { // Paper - don't run getEntities if we're not going to use its result; moved up -@@ -3736,9 +3736,16 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3765,9 +3765,16 @@ public abstract class LivingEntity extends Entity implements Attackable { return !this.isRemoved() && this.collides; // CraftBukkit } diff --git a/patches/server/0449-Expose-LivingEntity-hurt-direction.patch b/patches/server/0449-Expose-LivingEntity-hurt-direction.patch index ccb9fb6c2dfe..f43a7b04aa3f 100644 --- a/patches/server/0449-Expose-LivingEntity-hurt-direction.patch +++ b/patches/server/0449-Expose-LivingEntity-hurt-direction.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose LivingEntity hurt direction diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index acb2ccc8a940ea0ccd3d1f6d69c926d513f42872..80426e943b38e1cbde6ce80b3964df4d5ae23c94 100644 +index cb89b020d93ac838843ec2cbad562326a1e4257b..513e6505706e64f9410fa190014976dc469793af 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -187,7 +187,7 @@ public abstract class Player extends LivingEntity { +@@ -188,7 +188,7 @@ public abstract class Player extends LivingEntity { private Optional lastDeathLocation; @Nullable public FishingHook fishing; @@ -18,7 +18,7 @@ index acb2ccc8a940ea0ccd3d1f6d69c926d513f42872..80426e943b38e1cbde6ce80b3964df4d public Vec3 currentImpulseImpactPos; @Nullable diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 9393e9d21fcc41cb0f20b98d9f28c95b0e523f62..796945fb1a8b43987ed9f01375113b2c13ff67c0 100644 +index 8f4c4fed41676157b717c20a5ccbfe6ad4bdb3c4..87d067c3a83283931bc16dccf6a304142848cd6a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -125,6 +125,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { diff --git a/patches/server/0450-Add-OBSTRUCTED-reason-to-BedEnterResult.patch b/patches/server/0450-Add-OBSTRUCTED-reason-to-BedEnterResult.patch index c72796ff266a..decc5ee07c1a 100644 --- a/patches/server/0450-Add-OBSTRUCTED-reason-to-BedEnterResult.patch +++ b/patches/server/0450-Add-OBSTRUCTED-reason-to-BedEnterResult.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add OBSTRUCTED reason to BedEnterResult diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 4679e1399288db68ae0325cf62ea1a8fb6d6c80b..57e25bf61b2d25d736a97e9aadc8cfaddf29ea58 100644 +index dc7c73f36b7df05ee34e9686c99c44a24acecdcb..22bfea79a98963d4f1a7ac61fac7b194e929a4f6 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -303,6 +303,10 @@ public class CraftEventFactory { +@@ -304,6 +304,10 @@ public class CraftEventFactory { return BedEnterResult.TOO_FAR_AWAY; case NOT_SAFE: return BedEnterResult.NOT_SAFE; diff --git a/patches/server/0467-Add-BlockFailedDispenseEvent.patch b/patches/server/0467-Add-BlockFailedDispenseEvent.patch index 4d96419af9cf..9558081db4a8 100644 --- a/patches/server/0467-Add-BlockFailedDispenseEvent.patch +++ b/patches/server/0467-Add-BlockFailedDispenseEvent.patch @@ -32,10 +32,10 @@ index a1599eae0d8e9f0298fc6996ad03b0d6ba78f04f..083ddfb8fffa04dad6eeca2274f290a0 } else { ItemStack itemstack = tileentitydispenser.getItem(i); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 57e25bf61b2d25d736a97e9aadc8cfaddf29ea58..b6456c7fdd97925a8b68bdb80ff53c441f7996c7 100644 +index 22bfea79a98963d4f1a7ac61fac7b194e929a4f6..3ae196422395302a198b507c16347e7051ff5fd1 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -2058,4 +2058,12 @@ public class CraftEventFactory { +@@ -2077,4 +2077,12 @@ public class CraftEventFactory { return org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getPotion()); } // Paper end - WitchReadyPotionEvent diff --git a/patches/server/0482-Add-BlockPreDispenseEvent.patch b/patches/server/0482-Add-BlockPreDispenseEvent.patch index 76ee7d959e42..c177a17c489f 100644 --- a/patches/server/0482-Add-BlockPreDispenseEvent.patch +++ b/patches/server/0482-Add-BlockPreDispenseEvent.patch @@ -29,10 +29,10 @@ index 083ddfb8fffa04dad6eeca2274f290a08e62b5eb..45fafee2cf1893dccf477939dad05e9e } else { // CraftBukkit start - Fire event when pushing items into other inventories diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index b6456c7fdd97925a8b68bdb80ff53c441f7996c7..fd889f0af29703c85a78b8189881516d54d147a6 100644 +index 3ae196422395302a198b507c16347e7051ff5fd1..4be2bbf2c7001c8f716c1cd11b7624e9f3cbe79a 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -2065,5 +2065,11 @@ public class CraftEventFactory { +@@ -2084,5 +2084,11 @@ public class CraftEventFactory { io.papermc.paper.event.block.BlockFailedDispenseEvent event = new io.papermc.paper.event.block.BlockFailedDispenseEvent(block); return event.callEvent(); } diff --git a/patches/server/0486-Expand-EntityUnleashEvent.patch b/patches/server/0486-Expand-EntityUnleashEvent.patch index db29f0fdcdc6..02e8ed7290d5 100644 --- a/patches/server/0486-Expand-EntityUnleashEvent.patch +++ b/patches/server/0486-Expand-EntityUnleashEvent.patch @@ -121,10 +121,10 @@ index 3c0af74ed65610b1d5e3b72fdcf28c5a3423f0da..01173fc7177d78588978e087e63efda0 flag1 = true; } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index fd889f0af29703c85a78b8189881516d54d147a6..7310d8011fc27b17360887c048cb6eb79e2c0b1f 100644 +index 4be2bbf2c7001c8f716c1cd11b7624e9f3cbe79a..87c90c401c965ac65fcbe88bf2e1ef85bfd46755 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1570,8 +1570,10 @@ public class CraftEventFactory { +@@ -1574,8 +1574,10 @@ public class CraftEventFactory { Bukkit.getPluginManager().callEvent(new PlayerRecipeBookSettingsChangeEvent(player.getBukkitEntity(), bukkitType, open, filter)); } diff --git a/patches/server/0489-Add-EntityMoveEvent.patch b/patches/server/0489-Add-EntityMoveEvent.patch index 724779feec62..983c902724ee 100644 --- a/patches/server/0489-Add-EntityMoveEvent.patch +++ b/patches/server/0489-Add-EntityMoveEvent.patch @@ -29,10 +29,10 @@ index deabbf30a550ff1835530257177b8f47e4710414..6b2d00878a373680bc3d59e19ae11a2d public LevelChunk getChunkIfLoaded(int x, int z) { return this.chunkSource.getChunk(x, z, false); diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 536625307d7b820bd5293e70274e4d3885b04cba..9153119e21c75b3d523e10897935d931f633f1a5 100644 +index c7ead86c5048381c97d01a09ac8a5a84cd93c5db..7e4f3f88cbd79a497aeaa65b5fb0997d27d4ee0f 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3481,6 +3481,20 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3510,6 +3510,20 @@ public abstract class LivingEntity extends Entity implements Attackable { this.pushEntities(); this.level().getProfiler().pop(); diff --git a/patches/server/0492-Allow-adding-items-to-BlockDropItemEvent.patch b/patches/server/0492-Allow-adding-items-to-BlockDropItemEvent.patch index 0808b4dbcd2d..808e58550045 100644 --- a/patches/server/0492-Allow-adding-items-to-BlockDropItemEvent.patch +++ b/patches/server/0492-Allow-adding-items-to-BlockDropItemEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Allow adding items to BlockDropItemEvent diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 7310d8011fc27b17360887c048cb6eb79e2c0b1f..edb5d93684d959dbad0115643b3c9f5096ceee3a 100644 +index 87c90c401c965ac65fcbe88bf2e1ef85bfd46755..aa03917f96ed17fad53e07fa58225174846333fd 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -452,13 +452,30 @@ public class CraftEventFactory { +@@ -453,13 +453,30 @@ public class CraftEventFactory { } public static void handleBlockDropItemEvent(Block block, BlockState state, ServerPlayer player, List items) { diff --git a/patches/server/0505-Expand-world-key-API.patch b/patches/server/0505-Expand-world-key-API.patch index dab6d8f7befd..17d7ac06c4df 100644 --- a/patches/server/0505-Expand-world-key-API.patch +++ b/patches/server/0505-Expand-world-key-API.patch @@ -67,10 +67,10 @@ index 24c8e9a43affa8ca99c03562aefc3d6402c23281..ec92033fef581e42fb3f36acaba62689 // Check if a World already exists with the UID. if (this.getWorld(world.getUID()) != null) { diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 50322927460ec9464363617e3f7fe5ff8faa1f6f..00e4e899cf7ee5da89a77175e417115e7ba97afd 100644 +index 7427a81a779b82f96d34a3de228c9d59ee77fea7..7e538a5e742914aa496d76ffe5b450397367cf40 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -541,6 +541,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -527,6 +527,11 @@ public final class CraftMagicNumbers implements UnsafeValues { public int nextEntityId() { return net.minecraft.world.entity.Entity.nextEntityId(); } diff --git a/patches/server/0510-Expose-protocol-version.patch b/patches/server/0510-Expose-protocol-version.patch index 3bdee13099e7..37634ea47551 100644 --- a/patches/server/0510-Expose-protocol-version.patch +++ b/patches/server/0510-Expose-protocol-version.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Expose protocol version diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 00e4e899cf7ee5da89a77175e417115e7ba97afd..a71717fe99e78c480747cc61ab30b53b6667fde7 100644 +index 7e538a5e742914aa496d76ffe5b450397367cf40..86584a2308006a5b217841a97461707ce610d32f 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -546,6 +546,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -532,6 +532,11 @@ public final class CraftMagicNumbers implements UnsafeValues { public String getMainLevelName() { return ((net.minecraft.server.dedicated.DedicatedServer) net.minecraft.server.MinecraftServer.getServer()).getProperties().levelName; } diff --git a/patches/server/0512-Fix-PlayerItemConsumeEvent-cancelling-properly.patch b/patches/server/0512-Fix-PlayerItemConsumeEvent-cancelling-properly.patch index d9b5121ed15c..8663738c4bb9 100644 --- a/patches/server/0512-Fix-PlayerItemConsumeEvent-cancelling-properly.patch +++ b/patches/server/0512-Fix-PlayerItemConsumeEvent-cancelling-properly.patch @@ -9,10 +9,10 @@ till their item is switched. This patch clears the active item when the event is cancelled diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 9153119e21c75b3d523e10897935d931f633f1a5..cabbe2ee01b5da681ab14cfa76063f04fba0953c 100644 +index 7e4f3f88cbd79a497aeaa65b5fb0997d27d4ee0f..d2bb6d312e67462e36cffb8de26b88e3050d0518 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3982,6 +3982,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -4011,6 +4011,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.level().getCraftServer().getPluginManager().callEvent(event); if (event.isCancelled()) { diff --git a/patches/server/0520-Add-PlayerDeepSleepEvent.patch b/patches/server/0520-Add-PlayerDeepSleepEvent.patch index 169d874c90b4..c348ba15bc5b 100644 --- a/patches/server/0520-Add-PlayerDeepSleepEvent.patch +++ b/patches/server/0520-Add-PlayerDeepSleepEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add PlayerDeepSleepEvent diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 80426e943b38e1cbde6ce80b3964df4d5ae23c94..7e54b4b521d0cfe907db5cfa26129752b3de4355 100644 +index 513e6505706e64f9410fa190014976dc469793af..b444b24a92bd2209ee4104ae82c7cfa9c876c910 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -261,6 +261,13 @@ public abstract class Player extends LivingEntity { +@@ -262,6 +262,13 @@ public abstract class Player extends LivingEntity { if (this.isSleeping()) { ++this.sleepCounter; diff --git a/patches/server/0536-Expand-PlayerGameModeChangeEvent.patch b/patches/server/0536-Expand-PlayerGameModeChangeEvent.patch index f088e643a5cd..98696ab8cc7f 100644 --- a/patches/server/0536-Expand-PlayerGameModeChangeEvent.patch +++ b/patches/server/0536-Expand-PlayerGameModeChangeEvent.patch @@ -45,7 +45,7 @@ index 7f09119bc7d661e08a960dd2bd46006efe752d3e..d1da3600dc07107309b20ebe6e7c0c4d } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index bd1abd4ad5dc129df4c844571c9a91e7cc1748d9..04c9fe154a72804d7bb817bf3bbfccd8be96a6ee 100644 +index 47259d580460fd00c6c7a4e798e28667f333ca9c..205d0f5bc3da737f960fb0e795b959e611e48422 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -2087,10 +2087,18 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @@ -78,7 +78,7 @@ index bd1abd4ad5dc129df4c844571c9a91e7cc1748d9..04c9fe154a72804d7bb817bf3bbfccd8 } } -@@ -2505,6 +2513,16 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { +@@ -2512,6 +2520,16 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { } public void loadGameTypes(@Nullable CompoundTag nbt) { @@ -147,10 +147,10 @@ index 699658bd80eb88907041efb01d31e4051edb91de..58e5acbd00c4f8c0fcafa4f2c21b6a9f } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6924bf3fad82cd055523af835a83aa0ca3490625..868c6f5ee5d67b92ad5834e05f9f1795cca879db 100644 +index b2e5bf420d0d8e3f635632d91faf15e10f1988f6..00ccb9ae0d41ba87db2617853206d714a4225563 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1653,7 +1653,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1654,7 +1654,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { Preconditions.checkArgument(mode != null, "GameMode cannot be null"); if (this.getHandle().connection == null) return; diff --git a/patches/server/0537-ItemStack-repair-check-API.patch b/patches/server/0537-ItemStack-repair-check-API.patch index b2c00e80effe..9621b72ce24a 100644 --- a/patches/server/0537-ItemStack-repair-check-API.patch +++ b/patches/server/0537-ItemStack-repair-check-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] ItemStack repair check API diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index a71717fe99e78c480747cc61ab30b53b6667fde7..080ab25d3585552c1abd62a9992d48bf094fc065 100644 +index 86584a2308006a5b217841a97461707ce610d32f..86308d3633e02a85ea2727805990451af53033c8 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -551,6 +551,14 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -537,6 +537,14 @@ public final class CraftMagicNumbers implements UnsafeValues { public int getProtocolVersion() { return net.minecraft.SharedConstants.getCurrentVersion().getProtocolVersion(); } diff --git a/patches/server/0538-More-Enchantment-API.patch b/patches/server/0538-More-Enchantment-API.patch index 70558c14b929..692f90b66abe 100644 --- a/patches/server/0538-More-Enchantment-API.patch +++ b/patches/server/0538-More-Enchantment-API.patch @@ -10,7 +10,7 @@ Co-authored-by: Luis Co-authored-by: Janet Blackquill diff --git a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java -index 3ea6e6678432957c5caaff15ba20f8a8ddb393c9..10a74428ca8f8a869ba0d14f2a9b2126033df684 100644 +index fc6606e1bf2e2c35cb6c84af78859c3441775907..edf4df4d13dc814e98b897a3f8a5fd4757284299 100644 --- a/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java +++ b/src/main/java/org/bukkit/craftbukkit/enchantments/CraftEnchantment.java @@ -5,6 +5,7 @@ import java.util.Locale; @@ -21,7 +21,7 @@ index 3ea6e6678432957c5caaff15ba20f8a8ddb393c9..10a74428ca8f8a869ba0d14f2a9b2126 import net.minecraft.tags.EnchantmentTags; import org.bukkit.NamespacedKey; import org.bukkit.Registry; -@@ -92,7 +93,7 @@ public class CraftEnchantment extends Enchantment implements Handleable implements ItemType.Typed, Han +@@ -197,19 +197,36 @@ public class CraftItemType implements ItemType.Typed, Han // return CraftEquipmentSlot.getSlot(EntityInsentient.getEquipmentSlotForItem(CraftItemStack.asNMSCopy(ItemStack.of(this)))); // } @@ -37,24 +37,25 @@ index 3ad2d93fa4b5174531349e9dfce4f48944ee8cc5..431910368e6d5487456e8430ad7b027d + @Override public Multimap getDefaultAttributeModifiers(EquipmentSlot slot) { -- ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); + // Paper start - improve/fix item default attribute API + final net.minecraft.world.entity.EquipmentSlot nmsSlot = CraftEquipmentSlot.getNMS(slot); + return this.getDefaultAttributeModifiers(sg -> sg.test(nmsSlot)); + } ++ ++ private Multimap getDefaultAttributeModifiers(final java.util.function.Predicate slotPredicate) { ++ // Paper end - improve/fix item default attribute API + ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); -- ItemAttributeModifiers nmsDefaultAttributes = this.item.getDefaultAttributeModifiers(); + ItemAttributeModifiers nmsDefaultAttributes = this.item.components().getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY); + if (nmsDefaultAttributes.modifiers().isEmpty()) { + nmsDefaultAttributes = this.item.getDefaultAttributeModifiers(); + } +- - nmsDefaultAttributes.forEach(CraftEquipmentSlot.getNMS(slot), (key, value) -> { - Attribute attribute = CraftAttribute.minecraftToBukkit(key.value()); - defaultAttributes.put(attribute, CraftAttributeInstance.convert(value, slot)); - }); -+ private Multimap getDefaultAttributeModifiers(final java.util.function.Predicate slotPredicate) { -+ final ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); -+ ItemAttributeModifiers nmsDefaultAttributes = this.item.components().getOrDefault(DataComponents.ATTRIBUTE_MODIFIERS, ItemAttributeModifiers.EMPTY); -+ if (nmsDefaultAttributes.modifiers().isEmpty()) { -+ // we have to check both places cause for some reason vanilla puts default modifiers for armor in a different place -+ nmsDefaultAttributes = this.item.getDefaultAttributeModifiers(); -+ } ++ // Paper start - improve/fix item default attribute API + for (final net.minecraft.world.item.component.ItemAttributeModifiers.Entry entry : nmsDefaultAttributes.modifiers()) { + if (!slotPredicate.test(entry.slot())) continue; + final Attribute attribute = CraftAttribute.minecraftHolderToBukkit(entry.attribute()); @@ -66,22 +67,14 @@ index 3ad2d93fa4b5174531349e9dfce4f48944ee8cc5..431910368e6d5487456e8430ad7b027d return defaultAttributes.build(); } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 080ab25d3585552c1abd62a9992d48bf094fc065..a867c9de9c2c1798d8e9014f5114b0f4e32b3261 100644 +index 86308d3633e02a85ea2727805990451af53033c8..53cb6d7c2a734e46322b746f00c2bd0f09488126 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -400,15 +400,11 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -396,7 +396,11 @@ public final class CraftMagicNumbers implements UnsafeValues { @Override public Multimap getDefaultAttributeModifiers(Material material, EquipmentSlot slot) { -- ImmutableMultimap.Builder defaultAttributes = ImmutableMultimap.builder(); -- -- ItemAttributeModifiers nmsDefaultAttributes = CraftMagicNumbers.getItem(material).getDefaultAttributeModifiers(); -- nmsDefaultAttributes.forEach(CraftEquipmentSlot.getNMS(slot), (key, value) -> { -- Attribute attribute = CraftAttribute.minecraftToBukkit(key.value()); -- defaultAttributes.put(attribute, CraftAttributeInstance.convert(value, slot)); -- }); -- -- return defaultAttributes.build(); +- return material.getDefaultAttributeModifiers(slot); + // Paper start - delegate to method on ItemType + final org.bukkit.inventory.ItemType item = material.asItemType(); + Preconditions.checkArgument(item != null, material + " is not an item and does not have default attributes"); diff --git a/patches/server/0548-Add-PlayerKickEvent-causes.patch b/patches/server/0548-Add-PlayerKickEvent-causes.patch index 050372991d09..5cb94d101b7b 100644 --- a/patches/server/0548-Add-PlayerKickEvent-causes.patch +++ b/patches/server/0548-Add-PlayerKickEvent-causes.patch @@ -480,15 +480,15 @@ index f472dea0bd4f834c0c8f0aa59ae7cdae082b14af..2fa51c3a70f43cd23b8f494fc643d66c } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 868c6f5ee5d67b92ad5834e05f9f1795cca879db..c8a4677db69b0f4111d550ca457b9196e7acebdd 100644 +index 00ccb9ae0d41ba87db2617853206d714a4225563..ddd5bdf07f92f18ad27b34ce63a98a61f8263733 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -635,7 +635,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot if (this.getHandle().connection == null) return; -- this.getHandle().connection.disconnect(CraftChatMessage.fromStringOrEmpty(message)); -+ this.getHandle().connection.disconnect(CraftChatMessage.fromStringOrEmpty(message), org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause +- this.getHandle().connection.disconnect(CraftChatMessage.fromStringOrEmpty(message, true)); ++ this.getHandle().connection.disconnect(CraftChatMessage.fromStringOrEmpty(message, true), org.bukkit.event.player.PlayerKickEvent.Cause.PLUGIN); // Paper - kick event cause } // Paper start @@ -519,15 +519,15 @@ index 868c6f5ee5d67b92ad5834e05f9f1795cca879db..c8a4677db69b0f4111d550ca457b9196 if (msg.startsWith("/")) { this.getHandle().connection.handleCommand(msg); diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 9a1fffa0c07c24eed8bd6ea8f3cd26c9f926c54d..f3fa0340babfc5eb627066115164e2d885c602c2 100644 +index 824c4ad135ea5177f416687c7042639ed126b70b..39e56b95aaafbcd8ebe68fdefaace83702e9510d 100644 --- a/src/main/java/org/spigotmc/RestartCommand.java +++ b/src/main/java/org/spigotmc/RestartCommand.java @@ -74,7 +74,7 @@ public class RestartCommand extends Command // Kick all players for ( ServerPlayer p : com.google.common.collect.ImmutableList.copyOf( MinecraftServer.getServer().getPlayerList().players ) ) { -- p.connection.disconnect( CraftChatMessage.fromStringOrEmpty( SpigotConfig.restartMessage ) ); -+ p.connection.disconnect( CraftChatMessage.fromStringOrEmpty( SpigotConfig.restartMessage ), org.bukkit.event.player.PlayerKickEvent.Cause.RESTART_COMMAND); // Paper - kick event reason (cause is never used)) +- p.connection.disconnect( CraftChatMessage.fromStringOrEmpty( SpigotConfig.restartMessage, true ) ); ++ p.connection.disconnect( CraftChatMessage.fromStringOrEmpty( SpigotConfig.restartMessage, true ), org.bukkit.event.player.PlayerKickEvent.Cause.RESTART_COMMAND); // Paper - kick event reason (cause is never used)) } // Give the socket a chance to send the packets try diff --git a/patches/server/0557-Line-Of-Sight-Changes.patch b/patches/server/0557-Line-Of-Sight-Changes.patch index 6f42029c6835..1e1018607b5e 100644 --- a/patches/server/0557-Line-Of-Sight-Changes.patch +++ b/patches/server/0557-Line-Of-Sight-Changes.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Line Of Sight Changes diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index cabbe2ee01b5da681ab14cfa76063f04fba0953c..ca2d7db39d4f4ef485e1e4a49f2fe6b1c310baf7 100644 +index d2bb6d312e67462e36cffb8de26b88e3050d0518..85f3dcdc8349683cb79ce1d9fe56eff02af2a7a7 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3726,7 +3726,8 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3755,7 +3755,8 @@ public abstract class LivingEntity extends Entity implements Attackable { Vec3 vec3d = new Vec3(this.getX(), this.getEyeY(), this.getZ()); Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); diff --git a/patches/server/0559-Fix-potions-splash-events.patch b/patches/server/0559-Fix-potions-splash-events.patch index dc4c8cf69828..8d894f25e23c 100644 --- a/patches/server/0559-Fix-potions-splash-events.patch +++ b/patches/server/0559-Fix-potions-splash-events.patch @@ -143,10 +143,10 @@ index be787a5b52e90796d4f06e17e564f4324807c3e6..cb34cc9443da56c0497c7a0192c8b836 public boolean isLingering() { diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index edb5d93684d959dbad0115643b3c9f5096ceee3a..18b2a6db3adee2ac2630d500005e0a4034cfbad7 100644 +index aa03917f96ed17fad53e07fa58225174846333fd..b53b457b55d22eae7114cafc85e63e9aa5b0b4b2 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -876,6 +876,32 @@ public class CraftEventFactory { +@@ -877,6 +877,32 @@ public class CraftEventFactory { return event; } diff --git a/patches/server/0561-Fix-PlayerDropItemEvent-using-wrong-item.patch b/patches/server/0561-Fix-PlayerDropItemEvent-using-wrong-item.patch index 832b9e4954ea..3bb995b5ce53 100644 --- a/patches/server/0561-Fix-PlayerDropItemEvent-using-wrong-item.patch +++ b/patches/server/0561-Fix-PlayerDropItemEvent-using-wrong-item.patch @@ -31,23 +31,23 @@ index c81fd3e1108fb0a02f9240263404af2b968c8494..0d9de4c61c7b26a6ff37c12fde629161 } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 04c9fe154a72804d7bb817bf3bbfccd8be96a6ee..d413c4d445f42f6a923a49ce4f04b13c3ee28f7a 100644 +index 205d0f5bc3da737f960fb0e795b959e611e48422..07ddd327c625d58137f0368be36fb708ac64ff4c 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -2482,7 +2482,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { +@@ -2489,7 +2489,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { - if (retainOwnership) { + if (flag1) { if (!itemstack1.isEmpty()) { -- this.awardStat(Stats.ITEM_DROPPED.get(itemstack1.getItem()), stack.getCount()); +- this.awardStat(Stats.ITEM_DROPPED.get(itemstack1.getItem()), itemstack.getCount()); + this.awardStat(Stats.ITEM_DROPPED.get(itemstack1.getItem()), itemstack1.getCount()); // Paper - Fix PlayerDropItemEvent using wrong item } this.awardStat(Stats.DROP); diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 7e54b4b521d0cfe907db5cfa26129752b3de4355..c817d7cfa9bdef98aef6ac2df304ac5c2aa80649 100644 +index b444b24a92bd2209ee4104ae82c7cfa9c876c910..7fee6ffeb8ccde965fcc1454eb0d8c6b3637da41 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -744,6 +744,11 @@ public abstract class Player extends LivingEntity { +@@ -745,6 +745,11 @@ public abstract class Player extends LivingEntity { } double d0 = this.getEyeY() - 0.30000001192092896D; diff --git a/patches/server/0570-Add-missing-forceDrop-toggles.patch b/patches/server/0570-Add-missing-forceDrop-toggles.patch index d7c261ea7cbd..e11380293a31 100644 --- a/patches/server/0570-Add-missing-forceDrop-toggles.patch +++ b/patches/server/0570-Add-missing-forceDrop-toggles.patch @@ -56,20 +56,6 @@ index 8df42121aa22ec9f95a1b8627b64b0ff71e36314..7b3d5322611990406028e59b14099072 Panda.this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); int i = Panda.this.isLazy() ? Panda.this.random.nextInt(50) + 10 : Panda.this.random.nextInt(150) + 10; -diff --git a/src/main/java/net/minecraft/world/entity/animal/Wolf.java b/src/main/java/net/minecraft/world/entity/animal/Wolf.java -index faff64ae69eb689cea7754f221f374f8faa6e541..26b050599984ae3ba3827a0cabab255374e38c1e 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Wolf.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Wolf.java -@@ -472,7 +472,9 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder 0); - for (org.bukkit.inventory.ItemStack item : this.drops) { - loot.add(item); - } + this.dropCustomDeathLoot(this.serverLevel(), damageSource, flag); + + loot.addAll(this.drops); this.drops.clear(); // SPIGOT-5188: make sure to clear + } // Paper - fix player loottables running when mob loot gamerule is false diff --git a/patches/server/0700-Add-EntityDyeEvent-and-CollarColorable-interface.patch b/patches/server/0700-Add-EntityDyeEvent-and-CollarColorable-interface.patch index 16f87ae35005..0c6a5c56dafa 100644 --- a/patches/server/0700-Add-EntityDyeEvent-and-CollarColorable-interface.patch +++ b/patches/server/0700-Add-EntityDyeEvent-and-CollarColorable-interface.patch @@ -23,10 +23,10 @@ index d44807c16712afd37efdbf434d1afb12a7c3d343..2ed442c8d36f285420cf84a956e90b60 this.setCollarColor(enumcolor); itemstack.consume(1, player); diff --git a/src/main/java/net/minecraft/world/entity/animal/Wolf.java b/src/main/java/net/minecraft/world/entity/animal/Wolf.java -index 26b050599984ae3ba3827a0cabab255374e38c1e..c382a8f95f612db881b9cdbd07316d1ca1cd9c4b 100644 +index 22e37ac785340e2521f69a144a761732ce0a1a3f..31d7beca9797ab1a26792c3e30171a751c3846b1 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Wolf.java +++ b/src/main/java/net/minecraft/world/entity/animal/Wolf.java -@@ -451,6 +451,14 @@ public class Wolf extends TamableAnimal implements NeutralMob, VariantHolder implem +@@ -112,4 +112,26 @@ public class CraftBanner extends CraftBlockEntityState implem public CraftBanner copy(Location location) { return new CraftBanner(this, location); } diff --git a/patches/server/0726-More-Teleport-API.patch b/patches/server/0726-More-Teleport-API.patch index 8162e7b15e52..deb574d5df5d 100644 --- a/patches/server/0726-More-Teleport-API.patch +++ b/patches/server/0726-More-Teleport-API.patch @@ -112,7 +112,7 @@ index 47f24e390efd8eb4cb7f62b5203825f4160772b7..243ac4253a1541dba52126bad96682e4 private final org.bukkit.entity.Entity.Spigot spigot = new org.bukkit.entity.Entity.Spigot() { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 240b00ac76d299994129724372d899427c9604c7..d0005af63d4ae0081a39797cb62c5ff3e2efa537 100644 +index c92ca61b2af012e58f998c8b08c895007a423f67..17becfd5a08a87682d665151e3539f870b72f981 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1286,13 +1286,101 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -265,5 +265,5 @@ index 240b00ac76d299994129724372d899427c9604c7..d0005af63d4ae0081a39797cb62c5ff3 + entity.connection.internalTeleport(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch(), nms); + // Paper end - Teleport API } else { + entity.portalProcess = null; // SPIGOT-7785: there is no need to carry this over as it contains the old world/location and we might run into trouble if there is a portal in the same spot in both worlds // The respawn reason should never be used if the passed location is non null. - this.server.getHandle().respawn(entity, true, Entity.RemovalReason.CHANGED_DIMENSION, null, to); diff --git a/patches/server/0737-Add-NamespacedKey-biome-methods.patch b/patches/server/0737-Add-NamespacedKey-biome-methods.patch index d981229c6f23..0a5e2f5d8a71 100644 --- a/patches/server/0737-Add-NamespacedKey-biome-methods.patch +++ b/patches/server/0737-Add-NamespacedKey-biome-methods.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add NamespacedKey biome methods Co-authored-by: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com> diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 1a46245fed7a5fca532df7e3febb22f5effca764..7272f154644366c3c467b265aadc59b879a7b7bd 100644 +index 21461817aa27b5b7df8af186712a54b3c80ee576..2aa7aad2b4b7f2e7c81ccac28a1e6151055b0ba3 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -595,6 +595,21 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -589,6 +589,21 @@ public final class CraftMagicNumbers implements UnsafeValues { } // Paper end diff --git a/patches/server/0739-Stop-large-look-changes-from-crashing-the-server.patch b/patches/server/0739-Stop-large-look-changes-from-crashing-the-server.patch index 63adf0fc72fc..592bb75b032d 100644 --- a/patches/server/0739-Stop-large-look-changes-from-crashing-the-server.patch +++ b/patches/server/0739-Stop-large-look-changes-from-crashing-the-server.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Stop large look changes from crashing the server Co-authored-by: Jaren Knodel diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 8e11b085d2159b1df8bbe536beb66d9bed915373..1d6179d54ff2264d3489770b23fc7ba479c17f25 100644 +index fa9512da351ef92a8606b3e68ee060dac4c63346..e6335a55d87444d56d6f20dfc51cc4fc797de2cf 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3129,37 +3129,15 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3158,37 +3158,15 @@ public abstract class LivingEntity extends Entity implements Attackable { this.level().getProfiler().pop(); this.level().getProfiler().push("rangeChecks"); diff --git a/patches/server/0741-Missing-eating-regain-reason.patch b/patches/server/0741-Missing-eating-regain-reason.patch index ac2e750c7171..af804e161b36 100644 --- a/patches/server/0741-Missing-eating-regain-reason.patch +++ b/patches/server/0741-Missing-eating-regain-reason.patch @@ -18,10 +18,10 @@ index 2ed442c8d36f285420cf84a956e90b6036384ce0..23d4dcc82115fd1a0a77565a04723040 return InteractionResult.sidedSuccess(this.level().isClientSide()); diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java -index f0abcdda90650df279056009441f8a0426757664..bdc845b36b316069a626dad6cf31f5bcc5cd7d35 100644 +index 12d3ef81247f3088490f9b87d8068c2e2c6338c7..aecd17953dc117d369885d4c8d7b5c7c3a0f8f0f 100644 --- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java +++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java -@@ -384,7 +384,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -387,7 +387,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl boolean flag = this.getHealth() < this.getMaxHealth(); if (flag) { diff --git a/patches/server/0747-Mitigate-effects-of-WorldCreator-keepSpawnLoaded-ret.patch b/patches/server/0747-Mitigate-effects-of-WorldCreator-keepSpawnLoaded-ret.patch index 08af3020689f..e344e07414d9 100644 --- a/patches/server/0747-Mitigate-effects-of-WorldCreator-keepSpawnLoaded-ret.patch +++ b/patches/server/0747-Mitigate-effects-of-WorldCreator-keepSpawnLoaded-ret.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Mitigate effects of WorldCreator#keepSpawnLoaded ret type TODO: Remove in 1.21? diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -index 935c97af6fedde505c79956b24069770742a61cf..854e0eb25b03cfe2979bc10223219c5b45691bd9 100644 +index 1e050ef29593233694e0044bedf4c417d876f362..7437228d2b3a724769099b6d03cd83d1e47d9c69 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java +++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java -@@ -404,6 +404,12 @@ public class Commodore { +@@ -414,6 +414,12 @@ public class Commodore { super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, runtimeCbPkgPrefix() + "advancement/CraftAdvancement", "getDisplay0", desc, false); return; } diff --git a/patches/server/0755-Correctly-handle-interactions-with-items-on-cooldown.patch b/patches/server/0755-Correctly-handle-interactions-with-items-on-cooldown.patch index 5b6175374761..103b29fc686d 100644 --- a/patches/server/0755-Correctly-handle-interactions-with-items-on-cooldown.patch +++ b/patches/server/0755-Correctly-handle-interactions-with-items-on-cooldown.patch @@ -30,10 +30,10 @@ index 03d89f326d320c5d778c3d1e2db7d6b88753faec..717d015dd4637dd9d568b751be1dc104 this.interactResult = event.useItemInHand() == Event.Result.DENY; this.interactPosition = blockposition.immutable(); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 15afaf9b2fcff25288eb5739c9cc72fb301b875a..8233b2287c9cf3cfb4fd3f44d61c055e4076b355 100644 +index 4d5507e44d755588f18d992eb5f382f5f4fac273..d248977de4babc7921be8a64ce51577d31365933 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -546,6 +546,12 @@ public class CraftEventFactory { +@@ -547,6 +547,12 @@ public class CraftEventFactory { } public static PlayerInteractEvent callPlayerInteractEvent(net.minecraft.world.entity.player.Player who, Action action, BlockPos position, Direction direction, ItemStack itemstack, boolean cancelledBlock, InteractionHand hand, Vec3 targetPos) { @@ -46,7 +46,7 @@ index 15afaf9b2fcff25288eb5739c9cc72fb301b875a..8233b2287c9cf3cfb4fd3f44d61c055e Player player = (who == null) ? null : (Player) who.getBukkitEntity(); CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack); -@@ -580,6 +586,11 @@ public class CraftEventFactory { +@@ -581,6 +587,11 @@ public class CraftEventFactory { if (cancelledBlock) { event.setUseInteractedBlock(Event.Result.DENY); } diff --git a/patches/server/0757-Elder-Guardian-appearance-API.patch b/patches/server/0757-Elder-Guardian-appearance-API.patch index 05ac7bf793d2..f5fe07ced7f3 100644 --- a/patches/server/0757-Elder-Guardian-appearance-API.patch +++ b/patches/server/0757-Elder-Guardian-appearance-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Elder Guardian appearance API diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index bffb3c029e917ccfc4b092a5d213a4d0f7a42ce4..daa4aad117a6cf5f1e4e6da245e5c346122ac324 100644 +index f49b65a34e9ca249d9055ecf09262cfe4ab445c5..4ba269dbbb44cc4ef36db7386e4ccc99bd90bd72 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -3297,6 +3297,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3298,6 +3298,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } // Paper end diff --git a/patches/server/0762-Add-EntityToggleSitEvent.patch b/patches/server/0762-Add-EntityToggleSitEvent.patch index 66349ee5a3cc..c9aef59416b7 100644 --- a/patches/server/0762-Add-EntityToggleSitEvent.patch +++ b/patches/server/0762-Add-EntityToggleSitEvent.patch @@ -69,10 +69,10 @@ index 7b3d5322611990406028e59b1409907291e27b21..293d6891948e99ac9bd741008f7dcbc5 } diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java -index bdc845b36b316069a626dad6cf31f5bcc5cd7d35..71c1bc87ab5942fa07f187fa44089c08b5804e91 100644 +index aecd17953dc117d369885d4c8d7b5c7c3a0f8f0f..0388b09e1c4f03958384680ed487792a54007463 100644 --- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java +++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java -@@ -567,7 +567,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -570,7 +570,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl } public void sitDown() { @@ -81,7 +81,7 @@ index bdc845b36b316069a626dad6cf31f5bcc5cd7d35..71c1bc87ab5942fa07f187fa44089c08 this.makeSound(SoundEvents.CAMEL_SIT); this.setPose(Pose.SITTING); this.gameEvent(GameEvent.ENTITY_ACTION); -@@ -576,7 +576,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -579,7 +579,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl } public void standUp() { @@ -90,7 +90,7 @@ index bdc845b36b316069a626dad6cf31f5bcc5cd7d35..71c1bc87ab5942fa07f187fa44089c08 this.makeSound(SoundEvents.CAMEL_STAND); this.setPose(Pose.STANDING); this.gameEvent(GameEvent.ENTITY_ACTION); -@@ -585,6 +585,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -588,6 +588,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl } public void standUpInstantly() { diff --git a/patches/server/0768-Add-PrePlayerAttackEntityEvent.patch b/patches/server/0768-Add-PrePlayerAttackEntityEvent.patch index 02d71668dc1b..b0f3a0789006 100644 --- a/patches/server/0768-Add-PrePlayerAttackEntityEvent.patch +++ b/patches/server/0768-Add-PrePlayerAttackEntityEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add PrePlayerAttackEntityEvent diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 028dc5eda7bb93bb4714f6b223379803307add93..b5e1f39957f05670aec593f31ab2725fccffc692 100644 +index fab56040ecf496e74f583ec5d6c6c9861cfa4e13..ad334f149fe1b44d4ebe48489dcd2811ff1b5cd0 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1256,8 +1256,17 @@ public abstract class Player extends LivingEntity { +@@ -1257,8 +1257,17 @@ public abstract class Player extends LivingEntity { } public void attack(Entity target) { diff --git a/patches/server/0770-Add-Player-Warden-Warning-API.patch b/patches/server/0770-Add-Player-Warden-Warning-API.patch index 48110ad056eb..85b7ab61e89b 100644 --- a/patches/server/0770-Add-Player-Warden-Warning-API.patch +++ b/patches/server/0770-Add-Player-Warden-Warning-API.patch @@ -10,10 +10,10 @@ public net.minecraft.world.entity.monster.warden.WardenSpawnTracker cooldownTick public net.minecraft.world.entity.monster.warden.WardenSpawnTracker increaseWarningLevel()V diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index daa4aad117a6cf5f1e4e6da245e5c346122ac324..90ce5c386d46f10e14df67953938168c29d24c6a 100644 +index 4ba269dbbb44cc4ef36db7386e4ccc99bd90bd72..02b9233ecf929ac9ec7d304231d8bc66fc00dad4 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -3302,6 +3302,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3303,6 +3303,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player { public void showElderGuardian(boolean silent) { if (getHandle().connection != null) getHandle().connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, silent ? 0F : 1F)); } diff --git a/patches/server/0773-check-global-player-list-where-appropriate.patch b/patches/server/0773-check-global-player-list-where-appropriate.patch index 63bb71842c70..32596b991d7a 100644 --- a/patches/server/0773-check-global-player-list-where-appropriate.patch +++ b/patches/server/0773-check-global-player-list-where-appropriate.patch @@ -24,10 +24,10 @@ index 15607da2883653cd757a3220ddf79833afd39330..b9d3a98824fc146128f35244f5f15bba + // Paper end - check global player list where appropriate } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 1d6179d54ff2264d3489770b23fc7ba479c17f25..532f954a052eca3279f974450c2133837410282e 100644 +index e6335a55d87444d56d6f20dfc51cc4fc797de2cf..ec656b2505c143e453b540e3e0a2cbfa0b370cd3 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3694,7 +3694,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3723,7 +3723,7 @@ public abstract class LivingEntity extends Entity implements Attackable { } public void onItemPickup(ItemEntity item) { diff --git a/patches/server/0776-Friction-API.patch b/patches/server/0776-Friction-API.patch index 43e40c8c3354..dfa1fdc21bd2 100644 --- a/patches/server/0776-Friction-API.patch +++ b/patches/server/0776-Friction-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Friction API diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 532f954a052eca3279f974450c2133837410282e..c64fb799f2f40831cd25a409713c9b5081c76002 100644 +index ec656b2505c143e453b540e3e0a2cbfa0b370cd3..fd0e44ea6ff2868b06c8f0af14be998d95f9f46b 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -285,6 +285,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -25,7 +25,7 @@ index 532f954a052eca3279f974450c2133837410282e..c64fb799f2f40831cd25a409713c9b50 } public void setDiscardFriction(boolean noDrag) { -@@ -773,6 +774,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -774,6 +775,11 @@ public abstract class LivingEntity extends Entity implements Attackable { @Override public void addAdditionalSaveData(CompoundTag nbt) { @@ -37,7 +37,7 @@ index 532f954a052eca3279f974450c2133837410282e..c64fb799f2f40831cd25a409713c9b50 nbt.putFloat("Health", this.getHealth()); nbt.putShort("HurtTime", (short) this.hurtTime); nbt.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp); -@@ -816,6 +822,16 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -817,6 +823,16 @@ public abstract class LivingEntity extends Entity implements Attackable { } this.internalSetAbsorptionAmount(absorptionAmount); // Paper end - Check for NaN diff --git a/patches/server/0793-Flying-Fall-Damage.patch b/patches/server/0793-Flying-Fall-Damage.patch index 8b9d6862bd6a..4132811a77f9 100644 --- a/patches/server/0793-Flying-Fall-Damage.patch +++ b/patches/server/0793-Flying-Fall-Damage.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Flying Fall Damage diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index b5e1f39957f05670aec593f31ab2725fccffc692..98b3547b970e30e9cc009ef1fac9202590692d84 100644 +index ad334f149fe1b44d4ebe48489dcd2811ff1b5cd0..950ce40d268d89ff3c503116081db6c9ccd65329 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -195,6 +195,7 @@ public abstract class Player extends LivingEntity { +@@ -196,6 +196,7 @@ public abstract class Player extends LivingEntity { private boolean ignoreFallDamageFromCurrentImpulse; private int currentImpulseContextResetGraceTime; public boolean affectsSpawning = true; // Paper - Affects Spawning API @@ -16,7 +16,7 @@ index b5e1f39957f05670aec593f31ab2725fccffc692..98b3547b970e30e9cc009ef1fac92025 // CraftBukkit start public boolean fauxSleeping; -@@ -1690,7 +1691,7 @@ public abstract class Player extends LivingEntity { +@@ -1693,7 +1694,7 @@ public abstract class Player extends LivingEntity { @Override public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) { @@ -26,10 +26,10 @@ index b5e1f39957f05670aec593f31ab2725fccffc692..98b3547b970e30e9cc009ef1fac92025 } else { if (fallDistance >= 2.0F) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 6503bce4c0281619489adc01fa1da0c59b433875..207e72cad59a07c0750e9303dd21519c83ab2358 100644 +index 682c5e9328d965bf335bb06ac7aedf6d49b1c6cb..4bcceef859099405a3d78bc7e6b12c778e906d72 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -2580,6 +2580,19 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2581,6 +2581,19 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().onUpdateAbilities(); } diff --git a/patches/server/0797-Correctly-shrink-items-during-EntityResurrectEvent.patch b/patches/server/0797-Correctly-shrink-items-during-EntityResurrectEvent.patch index 58b1a31cc87e..8f9bf2cb2415 100644 --- a/patches/server/0797-Correctly-shrink-items-during-EntityResurrectEvent.patch +++ b/patches/server/0797-Correctly-shrink-items-during-EntityResurrectEvent.patch @@ -22,10 +22,10 @@ This patch corrects this behaviour by only shrinking the item if a totem of undying was found and the event was called uncancelled. diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index c64fb799f2f40831cd25a409713c9b5081c76002..8ec08a30875816d2b8258b56ee37a4938aed50fb 100644 +index fd0e44ea6ff2868b06c8f0af14be998d95f9f46b..7ad469bf4b88f9e33ad4aaebe18e41d25769444e 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1621,7 +1621,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1632,7 +1632,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.level().getCraftServer().getPluginManager().callEvent(event); if (!event.isCancelled()) { diff --git a/patches/server/0803-Add-EntityFertilizeEggEvent.patch b/patches/server/0803-Add-EntityFertilizeEggEvent.patch index a077b2cfc063..f8723b10b04f 100644 --- a/patches/server/0803-Add-EntityFertilizeEggEvent.patch +++ b/patches/server/0803-Add-EntityFertilizeEggEvent.patch @@ -69,10 +69,10 @@ index d34d8fe70379dcad9540739ec0ae1c94f01fc46b..fadd341ff398886a4da102eefa1beb95 this.playSound(SoundEvents.SNIFFER_EGG_PLOP, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 0.5F); } // Paper - Call EntityDropItemEvent diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 8233b2287c9cf3cfb4fd3f44d61c055e4076b355..63038e0ca10507751218fda5b9ace3cb6295e817 100644 +index d248977de4babc7921be8a64ce51577d31365933..85621246d1e29d678d8ec1b40893ff6650e08e1e 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -2128,4 +2128,28 @@ public class CraftEventFactory { +@@ -2147,4 +2147,28 @@ public class CraftEventFactory { return event.callEvent(); } // Paper end diff --git a/patches/server/0804-Fix-HumanEntity-drop-not-updating-the-client-inv.patch b/patches/server/0804-Fix-HumanEntity-drop-not-updating-the-client-inv.patch index a3e0925b4920..99130d8f1a46 100644 --- a/patches/server/0804-Fix-HumanEntity-drop-not-updating-the-client-inv.patch +++ b/patches/server/0804-Fix-HumanEntity-drop-not-updating-the-client-inv.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Fix HumanEntity#drop not updating the client inv public net.minecraft.server.level.ServerPlayer containerSynchronizer diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index e1150d36de56466ad9fdd5f2cdb4c30855d4af70..3d36d79a4e7f16f6face3465cdf54656984f3ebc 100644 +index 9ab3fc287480aedcb4033801d4f092719e933454..12ab8f7cde88cd6ce3ad474fe2843d5d30c3c0d7 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -@@ -750,8 +750,15 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -751,8 +751,15 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { // Paper end @Override public boolean dropItem(boolean dropAll) { diff --git a/patches/server/0807-Fix-advancement-triggers-for-entity-damage.patch b/patches/server/0807-Fix-advancement-triggers-for-entity-damage.patch index e4afda05ddba..4ebe57074046 100644 --- a/patches/server/0807-Fix-advancement-triggers-for-entity-damage.patch +++ b/patches/server/0807-Fix-advancement-triggers-for-entity-damage.patch @@ -23,10 +23,10 @@ index 2ebbf7954dc5e0d6c9d53327d05b725eec310086..c5bd2e90ad74ba08910f65a2e07b6f76 return !this.getResponse(); diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 8ec08a30875816d2b8258b56ee37a4938aed50fb..c8c52514777a97b35bd4fb2ac84565f07c8921d7 100644 +index 7ad469bf4b88f9e33ad4aaebe18e41d25769444e..ffc0fcd7c2075b44585bd754494f2f7c07788f47 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2359,7 +2359,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2388,7 +2388,7 @@ public abstract class LivingEntity extends Entity implements Attackable { // Duplicate triggers if blocking if (event.getDamage(DamageModifier.BLOCKING) < 0) { if (this instanceof ServerPlayer) { @@ -35,7 +35,7 @@ index 8ec08a30875816d2b8258b56ee37a4938aed50fb..c8c52514777a97b35bd4fb2ac84565f0 f2 = (float) -event.getDamage(DamageModifier.BLOCKING); if (f2 > 0.0F && f2 < 3.4028235E37F) { ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0F)); -@@ -2367,7 +2367,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2396,7 +2396,7 @@ public abstract class LivingEntity extends Entity implements Attackable { } if (damagesource.getEntity() instanceof ServerPlayer) { diff --git a/patches/server/0823-Expand-PlayerItemMendEvent.patch b/patches/server/0823-Expand-PlayerItemMendEvent.patch index 446aa3bb1015..5cc04e332156 100644 --- a/patches/server/0823-Expand-PlayerItemMendEvent.patch +++ b/patches/server/0823-Expand-PlayerItemMendEvent.patch @@ -30,10 +30,10 @@ index a758b2456acac23095fe4619ae10300a034cb460..a58ff67052fb5f33782f8b5c83465ec0 if (l > 0) { // this.value = l; // CraftBukkit - update exp value of orb for PlayerItemMendEvent calls // Paper - the value field should not be mutated here because it doesn't take "count" into account diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index ee5d93cd0c7ea7376e8488265d4e21610edeedc2..e84337b01ec7e5c530a4c6042b9386385eb58446 100644 +index d0cd2a8c99d607e36d37718b9e2c439f4a939535..7cd9b17e1863a369b578bc2a22d892246e7a02b9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1852,11 +1852,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1853,11 +1853,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { handle.serverLevel(), itemstack, amount ); int i = Math.min(possibleDurabilityFromXp, itemstack.getDamageValue()); @@ -49,10 +49,10 @@ index ee5d93cd0c7ea7376e8488265d4e21610edeedc2..e84337b01ec7e5c530a4c6042b938638 } } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 63038e0ca10507751218fda5b9ace3cb6295e817..214a1b8901947e8c08e8d7fc3f19e866a21350c8 100644 +index 85621246d1e29d678d8ec1b40893ff6650e08e1e..b1c568200fb6870843b8ace4a9b15041980aceeb 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1267,10 +1267,10 @@ public class CraftEventFactory { +@@ -1271,10 +1271,10 @@ public class CraftEventFactory { return event; } diff --git a/patches/server/0838-Call-missing-BlockDispenseEvent.patch b/patches/server/0838-Call-missing-BlockDispenseEvent.patch index 97050595b8c1..e4be646fe33e 100644 --- a/patches/server/0838-Call-missing-BlockDispenseEvent.patch +++ b/patches/server/0838-Call-missing-BlockDispenseEvent.patch @@ -50,10 +50,10 @@ index 96db0b1041a4c0f054d4f3f2bdced960b119664e..78951f50188528718cdb3dbbaabe3f9f 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); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 214a1b8901947e8c08e8d7fc3f19e866a21350c8..35b6443d15678ec84271dcebf29b98b36df97a6e 100644 +index b1c568200fb6870843b8ace4a9b15041980aceeb..cbb5baae60e682bc250568327737a1b1994ceb76 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -2129,6 +2129,32 @@ public class CraftEventFactory { +@@ -2148,6 +2148,32 @@ public class CraftEventFactory { } // Paper end diff --git a/patches/server/0843-Fix-BanList-API.patch b/patches/server/0843-Fix-BanList-API.patch index dcc17ccb44a1..995aa9c90aa7 100644 --- a/patches/server/0843-Fix-BanList-API.patch +++ b/patches/server/0843-Fix-BanList-API.patch @@ -208,10 +208,10 @@ index 172202accf4448a933fcf1ff820316c7910dd7f7..50ee7656580d386db473c054f5c5ec57 return null; } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index e84337b01ec7e5c530a4c6042b9386385eb58446..85f403c07ff146a0da232ac7bfc0551a2fa2601b 100644 +index 7cd9b17e1863a369b578bc2a22d892246e7a02b9..49e22acbcdcdb2108b360c2a6e40c752c12ab9f6 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1746,23 +1746,23 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1747,23 +1747,23 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override @@ -240,7 +240,7 @@ index e84337b01ec7e5c530a4c6042b9386385eb58446..85f403c07ff146a0da232ac7bfc0551a if (kickPlayer) { this.kickPlayer(reason); } -@@ -1770,12 +1770,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1771,12 +1771,12 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } @Override diff --git a/patches/server/0847-ExperienceOrb-should-call-EntitySpawnEvent.patch b/patches/server/0847-ExperienceOrb-should-call-EntitySpawnEvent.patch index 542bede5c40c..e3ebc7591800 100644 --- a/patches/server/0847-ExperienceOrb-should-call-EntitySpawnEvent.patch +++ b/patches/server/0847-ExperienceOrb-should-call-EntitySpawnEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] ExperienceOrb should call EntitySpawnEvent diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 35b6443d15678ec84271dcebf29b98b36df97a6e..7b1de2fddd5ff236c477439142c6e38a580d7f56 100644 +index cbb5baae60e682bc250568327737a1b1994ceb76..01f6d9a3339529bc3a1ec2bacae422b86f1eb253 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -736,7 +736,8 @@ public class CraftEventFactory { +@@ -737,7 +737,8 @@ public class CraftEventFactory { // Spigot start - SPIGOT-7523: Merge after spawn event and only merge if the event was not cancelled (gets checked above) if (entity instanceof net.minecraft.world.entity.ExperienceOrb xp) { double radius = world.spigotConfig.expMerge; diff --git a/patches/server/0861-Fix-custom-statistic-criteria-creation.patch b/patches/server/0861-Fix-custom-statistic-criteria-creation.patch index f399187f50f7..23faf0bb9ffb 100644 --- a/patches/server/0861-Fix-custom-statistic-criteria-creation.patch +++ b/patches/server/0861-Fix-custom-statistic-criteria-creation.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix custom statistic criteria creation diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 7272f154644366c3c467b265aadc59b879a7b7bd..a98fcfcf71b2a072d60120046d9aac9ad4546196 100644 +index 2aa7aad2b4b7f2e7c81ccac28a1e6151055b0ba3..e74f4a16d3e1e7cf716b93057c8b42e8ed0f3503 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -610,6 +610,14 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -604,6 +604,14 @@ public final class CraftMagicNumbers implements UnsafeValues { } // Paper end - namespaced key biome methods diff --git a/patches/server/0870-Add-Listing-API-for-Player.patch b/patches/server/0870-Add-Listing-API-for-Player.patch index 45d76a9d2230..8f4e9c9d4032 100644 --- a/patches/server/0870-Add-Listing-API-for-Player.patch +++ b/patches/server/0870-Add-Listing-API-for-Player.patch @@ -119,7 +119,7 @@ index be6bf7afa3cea4ed48f363e89ccd079062edc8d9..9b1a6d8351fb473eec75a2fd08fb892b // Paper end - Use single player info update packet on join player.sentListPacket = true; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 296bb88ed34f499535ef0b9fdffa67b7de81c60b..e4de4ed09b20ed224eadcbc6d650192897c4def5 100644 +index 4c5249eab8e59b46c902f2cb65f90aa2a66a33d4..204e4e4dd197088457cd6d2a18f86287ca3324b2 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -201,6 +201,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @@ -130,7 +130,7 @@ index 296bb88ed34f499535ef0b9fdffa67b7de81c60b..e4de4ed09b20ed224eadcbc6d6501928 private static final WeakHashMap> pluginWeakReferences = new WeakHashMap<>(); private int hash = 0; private double health = 20; -@@ -2091,7 +2092,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2092,7 +2093,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { otherPlayer.setUUID(uuidOverride); } // Paper end @@ -139,7 +139,7 @@ index 296bb88ed34f499535ef0b9fdffa67b7de81c60b..e4de4ed09b20ed224eadcbc6d6501928 if (original != null) otherPlayer.setUUID(original); // Paper - uuid override } -@@ -2195,6 +2196,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2196,6 +2197,41 @@ public class CraftPlayer extends CraftHumanEntity implements Player { return (entity != null) ? this.canSee(entity) : false; // If we can't find it, we can't see it } diff --git a/patches/server/0872-Add-BlockFace-to-BlockDamageEvent.patch b/patches/server/0872-Add-BlockFace-to-BlockDamageEvent.patch index 7ad1e7c9e44f..7721e78d75a9 100644 --- a/patches/server/0872-Add-BlockFace-to-BlockDamageEvent.patch +++ b/patches/server/0872-Add-BlockFace-to-BlockDamageEvent.patch @@ -18,10 +18,10 @@ index c680f081ba548f84f07a968a46811090c53e57e3..d839f8df658c894f144ba4637d290ffb if (blockEvent.isCancelled()) { // Let the client know the block still exists diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 7b1de2fddd5ff236c477439142c6e38a580d7f56..361ad90853dbd7dc2d502f224f355d6d5e9c92cc 100644 +index 01f6d9a3339529bc3a1ec2bacae422b86f1eb253..9f6d459146f502909d262a7178d5b8d5575c563c 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -651,13 +651,13 @@ public class CraftEventFactory { +@@ -652,13 +652,13 @@ public class CraftEventFactory { /** * BlockDamageEvent */ diff --git a/patches/server/0882-Add-titleOverride-to-InventoryOpenEvent.patch b/patches/server/0882-Add-titleOverride-to-InventoryOpenEvent.patch index 3bb0db6ef273..c8738e3bfc79 100644 --- a/patches/server/0882-Add-titleOverride-to-InventoryOpenEvent.patch +++ b/patches/server/0882-Add-titleOverride-to-InventoryOpenEvent.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add titleOverride to InventoryOpenEvent diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 46d6fb2591f47c245446db210a00cbaa1e2bd99b..184f3c7a1304f4f9d2aaeae27172be9d853c30de 100644 +index b5035cc4b5cfa246487dc5091cc5d43e04253d6d..f568fa18ddcb1a1cd060c469edd6db45431bb53c 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -1659,12 +1659,17 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { @@ -37,7 +37,7 @@ index 46d6fb2591f47c245446db210a00cbaa1e2bd99b..184f3c7a1304f4f9d2aaeae27172be9d this.initMenu(container); return OptionalInt.of(this.containerCounter); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java -index 3d36d79a4e7f16f6face3465cdf54656984f3ebc..41f3cdec7deabf34358b8087df77169f85a5b919 100644 +index 12ab8f7cde88cd6ce3ad474fe2843d5d30c3c0d7..c1bad887d1340ebc7c63fda3dceff929e4a44517 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java @@ -358,12 +358,16 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { @@ -58,7 +58,7 @@ index 3d36d79a4e7f16f6face3465cdf54656984f3ebc..41f3cdec7deabf34358b8087df77169f //player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, CraftChatMessage.fromString(title)[0])); // Paper - comment if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen -@@ -439,7 +443,10 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -440,7 +444,10 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { } // Trigger an INVENTORY_OPEN event @@ -70,7 +70,7 @@ index 3d36d79a4e7f16f6face3465cdf54656984f3ebc..41f3cdec7deabf34358b8087df77169f if (container == null) { return; } -@@ -450,6 +457,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { +@@ -451,6 +458,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { //String title = inventory.getTitle(); // Paper - comment net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper @@ -79,10 +79,10 @@ index 3d36d79a4e7f16f6face3465cdf54656984f3ebc..41f3cdec7deabf34358b8087df77169f if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen player.containerMenu = container; diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 361ad90853dbd7dc2d502f224f355d6d5e9c92cc..c9a38f6b91ac538aea4c4a6f23d18415585a931b 100644 +index 9f6d459146f502909d262a7178d5b8d5575c563c..e079e8f4078078d737a9d554dbcd2568b1a1f9eb 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1384,10 +1384,21 @@ public class CraftEventFactory { +@@ -1388,10 +1388,21 @@ public class CraftEventFactory { } public static AbstractContainerMenu callInventoryOpenEvent(ServerPlayer player, AbstractContainerMenu container) { @@ -105,7 +105,7 @@ index 361ad90853dbd7dc2d502f224f355d6d5e9c92cc..c9a38f6b91ac538aea4c4a6f23d18415 if (player.containerMenu != player.inventoryMenu) { // fire INVENTORY_CLOSE if one already open player.connection.handleContainerClose(new ServerboundContainerClosePacket(player.containerMenu.containerId), InventoryCloseEvent.Reason.OPEN_NEW); // Paper - Inventory close reason } -@@ -1402,10 +1413,10 @@ public class CraftEventFactory { +@@ -1406,10 +1417,10 @@ public class CraftEventFactory { if (event.isCancelled()) { container.transferTo(player.containerMenu, craftPlayer); diff --git a/patches/server/0899-Fix-UnsafeValues-loadAdvancement.patch b/patches/server/0899-Fix-UnsafeValues-loadAdvancement.patch index 205c42df23b3..ff1703614046 100644 --- a/patches/server/0899-Fix-UnsafeValues-loadAdvancement.patch +++ b/patches/server/0899-Fix-UnsafeValues-loadAdvancement.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Fix UnsafeValues#loadAdvancement diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index a98fcfcf71b2a072d60120046d9aac9ad4546196..17caf21e23aa7f5a5216923e73aae94a59bcac44 100644 +index e74f4a16d3e1e7cf716b93057c8b42e8ed0f3503..278ef7b7cd2cf95dcf38fb4cadfd2acfcc9c4dc5 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -322,9 +322,30 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -318,9 +318,30 @@ public final class CraftMagicNumbers implements UnsafeValues { ResourceLocation minecraftkey = CraftNamespacedKey.toMinecraft(key); JsonElement jsonelement = ServerAdvancementManager.GSON.fromJson(advancement, JsonElement.class); diff --git a/patches/server/0900-Add-player-idle-duration-API.patch b/patches/server/0900-Add-player-idle-duration-API.patch index e9d6bf10c6ad..eac8276c5dfb 100644 --- a/patches/server/0900-Add-player-idle-duration-API.patch +++ b/patches/server/0900-Add-player-idle-duration-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add player idle duration API Implements API for getting and resetting a player's idle duration. diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index d5757fa3d4254535448eb040593c8c23995b7bc9..141b79346d6826a5fcea04f2d65506448cbed254 100644 +index ea742de14280c64f94461ebfb4647536a1dddb4f..bababc918704a671ee4635ba0c79219d94474821 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -3418,6 +3418,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3419,6 +3419,18 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } // Paper end diff --git a/patches/server/0907-Broadcast-take-item-packets-with-collector-as-source.patch b/patches/server/0907-Broadcast-take-item-packets-with-collector-as-source.patch index f114e5e960e8..25d46b180a52 100644 --- a/patches/server/0907-Broadcast-take-item-packets-with-collector-as-source.patch +++ b/patches/server/0907-Broadcast-take-item-packets-with-collector-as-source.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Broadcast take item packets with collector as source This fixes players (which can't view the collector) seeing item pickups with themselves as the target. diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index c8c52514777a97b35bd4fb2ac84565f07c8921d7..9a2b874594e2f04f59b7d2be389223604d56219a 100644 +index ffc0fcd7c2075b44585bd754494f2f7c07788f47..2ad88bc281861f53b5d65ce81448a334849ffff0 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3720,7 +3720,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3749,7 +3749,7 @@ public abstract class LivingEntity extends Entity implements Attackable { public void take(Entity item, int count) { if (!item.isRemoved() && !this.level().isClientSide && (item instanceof ItemEntity || item instanceof AbstractArrow || item instanceof ExperienceOrb)) { diff --git a/patches/server/0911-Fix-several-issues-with-EntityBreedEvent.patch b/patches/server/0911-Fix-several-issues-with-EntityBreedEvent.patch index 9e82a901a067..6a97d9fb9e5f 100644 --- a/patches/server/0911-Fix-several-issues-with-EntityBreedEvent.patch +++ b/patches/server/0911-Fix-several-issues-with-EntityBreedEvent.patch @@ -11,10 +11,10 @@ also changed. Also in several places, the breed item was stored after it was decreased by one to consume the item. diff --git a/src/main/java/net/minecraft/world/entity/animal/Animal.java b/src/main/java/net/minecraft/world/entity/animal/Animal.java -index 370c444153d04fe7896952219604d83a19a996e2..e96fca314bebea5fcdb684d3478af1b6dc5f13cf 100644 +index b46352b328178df2a48d1c9e895bed3fabd2c292..1808e1b01afa3041a54c9c9a7586d4d61960527a 100644 --- a/src/main/java/net/minecraft/world/entity/animal/Animal.java +++ b/src/main/java/net/minecraft/world/entity/animal/Animal.java -@@ -147,8 +147,9 @@ public abstract class Animal extends AgeableMob { +@@ -148,8 +148,9 @@ public abstract class Animal extends AgeableMob { int i = this.getAge(); if (!this.level().isClientSide && i == 0 && this.canFallInLove()) { @@ -25,7 +25,7 @@ index 370c444153d04fe7896952219604d83a19a996e2..e96fca314bebea5fcdb684d3478af1b6 return InteractionResult.SUCCESS; } -@@ -174,10 +175,18 @@ public abstract class Animal extends AgeableMob { +@@ -175,10 +176,18 @@ public abstract class Animal extends AgeableMob { return this.inLove <= 0; } @@ -44,7 +44,7 @@ index 370c444153d04fe7896952219604d83a19a996e2..e96fca314bebea5fcdb684d3478af1b6 return; } this.inLove = entityEnterLoveModeEvent.getTicksInLove(); -@@ -185,7 +194,7 @@ public abstract class Animal extends AgeableMob { +@@ -186,7 +195,7 @@ public abstract class Animal extends AgeableMob { if (player != null) { this.loveCause = player.getUUID(); } @@ -69,10 +69,10 @@ index 293d6891948e99ac9bd741008f7dcbc5fc1a2e3d..e108f876d3f129c6287f13d68427aed2 if (this.level().isClientSide || this.isSitting() || this.isInWater()) { return InteractionResult.PASS; diff --git a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java -index 38bb6e627c5500923103c3c9552eddcc63257a1d..792d9039ac0561464c666977ff8308e4c629e5eb 100644 +index 4eb305bc77767531efb6f9d299216248d4ee39d2..729fd2d52dd48e25ee7a077a3ffafc80ecef7c9f 100644 --- a/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java +++ b/src/main/java/net/minecraft/world/entity/animal/armadillo/Armadillo.java -@@ -348,8 +348,8 @@ public class Armadillo extends Animal { +@@ -352,8 +352,8 @@ public class Armadillo extends Animal { } @Override @@ -84,10 +84,10 @@ index 38bb6e627c5500923103c3c9552eddcc63257a1d..792d9039ac0561464c666977ff8308e4 } diff --git a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java -index 71c1bc87ab5942fa07f187fa44089c08b5804e91..147974651d37e81d81ca97bfa31c9df9867492be 100644 +index 0388b09e1c4f03958384680ed487792a54007463..8941752e4600ccd11b3fa1147b2e414785589eed 100644 --- a/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java +++ b/src/main/java/net/minecraft/world/entity/animal/camel/Camel.java -@@ -390,7 +390,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl +@@ -393,7 +393,7 @@ public class Camel extends AbstractHorse implements PlayerRideableJumping, Saddl boolean flag1 = this.isTamed() && this.getAge() == 0 && this.canFallInLove(); if (flag1) { diff --git a/patches/server/0915-Don-t-fire-sync-events-during-worldgen.patch b/patches/server/0915-Don-t-fire-sync-events-during-worldgen.patch index b115ced80b51..01cd11852fc2 100644 --- a/patches/server/0915-Don-t-fire-sync-events-during-worldgen.patch +++ b/patches/server/0915-Don-t-fire-sync-events-during-worldgen.patch @@ -68,10 +68,10 @@ index 5fb3279342506611882b5780cfbee0371919c93c..b98f9246b60daf31460f41ce214dfa7c }, () -> { EntityType.LOGGER.warn("Skipping Entity with id {}", nbt.getString("id")); diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 9a2b874594e2f04f59b7d2be389223604d56219a..3f788e88604b77761c5add39450cf1640604c0f0 100644 +index 2ad88bc281861f53b5d65ce81448a334849ffff0..2cbb4ff57117382791eefa4881fc0b328c77d58a 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1137,6 +1137,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1138,6 +1138,11 @@ public abstract class LivingEntity extends Entity implements Attackable { } public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) { @@ -83,7 +83,7 @@ index 9a2b874594e2f04f59b7d2be389223604d56219a..3f788e88604b77761c5add39450cf164 // org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot // Paper - move to API if (this.isTickingEffects) { this.effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); -@@ -1156,10 +1161,13 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1157,10 +1162,13 @@ public abstract class LivingEntity extends Entity implements Attackable { override = new MobEffectInstance(mobeffect1).update(mobeffect); } @@ -97,7 +97,7 @@ index 9a2b874594e2f04f59b7d2be389223604d56219a..3f788e88604b77761c5add39450cf164 // CraftBukkit end if (mobeffect1 == null) { -@@ -1168,7 +1176,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1169,7 +1177,7 @@ public abstract class LivingEntity extends Entity implements Attackable { flag = true; mobeffect.onEffectAdded(this); // CraftBukkit start diff --git a/patches/server/0918-Restore-vanilla-entity-drops-behavior.patch b/patches/server/0918-Restore-vanilla-entity-drops-behavior.patch index 5d48caea92b9..f0dcb68052c2 100644 --- a/patches/server/0918-Restore-vanilla-entity-drops-behavior.patch +++ b/patches/server/0918-Restore-vanilla-entity-drops-behavior.patch @@ -9,14 +9,14 @@ on dropping the item instead of generalizing it for all dropped items like CB does. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 184f3c7a1304f4f9d2aaeae27172be9d853c30de..3cbb59df34156479d24a8251f2b3acbb5e60dc2c 100644 +index f568fa18ddcb1a1cd060c469edd6db45431bb53c..09e60ea5c25f23bcc7e24f16c7a31f616d249ff9 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -978,22 +978,20 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { if (this.isRemoved()) { return; } -- java.util.List loot = new java.util.ArrayList(this.getInventory().getContainerSize()); +- java.util.List loot = new java.util.ArrayList<>(this.getInventory().getContainerSize()); + List loot = new java.util.ArrayList<>(this.getInventory().getContainerSize()); // Paper - Restore vanilla drops behavior boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator(); @@ -31,24 +31,13 @@ index 184f3c7a1304f4f9d2aaeae27172be9d853c30de..3cbb59df34156479d24a8251f2b3acbb if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule) this.dropFromLootTable(damageSource, this.lastHurtByPlayerTime > 0); -- for (org.bukkit.inventory.ItemStack item : this.drops) { -- loot.add(item); -- } +- this.dropCustomDeathLoot(this.serverLevel(), damageSource, flag); +- +- loot.addAll(this.drops); + loot.addAll(this.drops); // Paper this.drops.clear(); // SPIGOT-5188: make sure to clear } // Paper - fix player loottables running when mob loot gamerule is false -@@ -2530,8 +2528,8 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { - } - - @Override -- public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership) { -- ItemEntity entityitem = super.drop(stack, throwRandomly, retainOwnership); -+ public ItemEntity drop(ItemStack stack, boolean throwRandomly, boolean retainOwnership, boolean callDropEvent) { // Paper - Restore vanilla drops behavior; override method with most params -+ ItemEntity entityitem = super.drop(stack, throwRandomly, retainOwnership, callDropEvent); // Paper - Restore vanilla drops behavior; override method with most params - - if (entityitem == null) { - return null; diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 24aacf9997c9ea0bd68ef3803f4a3ee4a920ab44..363fe1aff439983199f5137547cef9516fbab2a8 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java @@ -104,7 +93,7 @@ index 24aacf9997c9ea0bd68ef3803f4a3ee4a920ab44..363fe1aff439983199f5137547cef951 return this.spawnAtLocation(entityitem); } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 3f788e88604b77761c5add39450cf1640604c0f0..3e58fa4160fd4e4e5b5d00ba8f963b1b74be2663 100644 +index 2cbb4ff57117382791eefa4881fc0b328c77d58a..3def6b7919484c330bc1c4aea1a8e2c6ad21f999 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -278,7 +278,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -165,10 +154,10 @@ index 5bcb9a53ebebeef4bd6ec2458df4b63002ebd804..2f398750bfee5758ad8b1367b6fc1436 } } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index c9a38f6b91ac538aea4c4a6f23d18415585a931b..bec1f62559b42acee6c955baf7851aecb9179e16 100644 +index e079e8f4078078d737a9d554dbcd2568b1a1f9eb..1d958323eccd4cf5e369e99e32d2f1dec0959591 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -965,18 +965,24 @@ public class CraftEventFactory { +@@ -966,18 +966,24 @@ public class CraftEventFactory { } public static EntityDeathEvent callEntityDeathEvent(net.minecraft.world.entity.LivingEntity victim, DamageSource damageSource) { @@ -197,7 +186,7 @@ index c9a38f6b91ac538aea4c4a6f23d18415585a931b..bec1f62559b42acee6c955baf7851aec populateFields(victim, event); // Paper - make cancellable CraftWorld world = (CraftWorld) entity.getWorld(); Bukkit.getServer().getPluginManager().callEvent(event); -@@ -990,20 +996,24 @@ public class CraftEventFactory { +@@ -991,20 +997,24 @@ public class CraftEventFactory { victim.expToDrop = event.getDroppedExp(); lootCheck.run(); // Paper - advancement triggers before destroying items @@ -238,8 +227,8 @@ index c9a38f6b91ac538aea4c4a6f23d18415585a931b..bec1f62559b42acee6c955baf7851aec + // Paper end - Restore vanilla drops behavior if (stack == null || stack.getType() == Material.AIR) continue; -- world.dropItem(entity.getLocation(), stack); -+ drop.runConsumer(world, entity.getLocation()); // Paper - Restore vanilla drops behavior +- victim.drop(CraftItemStack.asNMSCopy(stack), true, false, false); // SPIGOT-7800, SPIGOT-7801: Vanilla Behaviour for dropped items ++ drop.runConsumer(entity.getWorld(), entity.getLocation()); // Paper - Restore vanilla drops behavior } return event; diff --git a/patches/server/0922-Fix-NPE-on-null-loc-for-EntityTeleportEvent.patch b/patches/server/0922-Fix-NPE-on-null-loc-for-EntityTeleportEvent.patch index 4c7c476e6dbf..72b2cc189acc 100644 --- a/patches/server/0922-Fix-NPE-on-null-loc-for-EntityTeleportEvent.patch +++ b/patches/server/0922-Fix-NPE-on-null-loc-for-EntityTeleportEvent.patch @@ -26,10 +26,10 @@ index a306b30af19277386a2f3e560b4902a8b5796f2a..54851f6cc0d5fddb32a9a1e84a4f5ae4 x = to.getX(); y = to.getY(); diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 3e58fa4160fd4e4e5b5d00ba8f963b1b74be2663..a7eec0a1f053d0f4b68604c48aba95420049cfdd 100644 +index 3def6b7919484c330bc1c4aea1a8e2c6ad21f999..ff16c7196b146388c526e3100e561be771ca8a91 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -4200,7 +4200,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -4229,7 +4229,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (!(this instanceof ServerPlayer)) { EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.level().getWorld(), d3, d4, d5), new Location(this.level().getWorld(), d0, d6, d2)); this.level().getCraftServer().getPluginManager().callEvent(teleport); diff --git a/patches/server/0923-Add-experience-points-API.patch b/patches/server/0923-Add-experience-points-API.patch index 9b9a45f7bea5..e4e988cec20b 100644 --- a/patches/server/0923-Add-experience-points-API.patch +++ b/patches/server/0923-Add-experience-points-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add experience points API diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index 98b3547b970e30e9cc009ef1fac9202590692d84..bef9c905d884fec70f6faecff4d73c5484a412f5 100644 +index 950ce40d268d89ff3c503116081db6c9ccd65329..454b29d8c9e42e328933aa578f49d28f1e77898a 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1866,7 +1866,7 @@ public abstract class Player extends LivingEntity { +@@ -1869,7 +1869,7 @@ public abstract class Player extends LivingEntity { } public int getXpNeededForNextLevel() { @@ -18,10 +18,10 @@ index 98b3547b970e30e9cc009ef1fac9202590692d84..bef9c905d884fec70f6faecff4d73c54 // Paper start - send while respecting visibility private static void sendSoundEffect(Player fromEntity, double x, double y, double z, SoundEvent soundEffect, SoundSource soundCategory, float volume, float pitch) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index c24f27206dea30b99f2c5b80d8e011b7bc2233e8..4a886f11b10395143879e1c1795afc269eed109d 100644 +index cb2cda2cb472b6ca0dd9b4fd1aea74ec3d215bbf..3a1777539f378f1e41bbd6b972c12a726afe5feb 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -1920,6 +1920,49 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -1921,6 +1921,49 @@ public class CraftPlayer extends CraftHumanEntity implements Player { Preconditions.checkArgument(exp >= 0, "Total experience points must not be negative (%s)", exp); this.getHandle().totalExperience = exp; } diff --git a/patches/server/0924-Add-drops-to-shear-events.patch b/patches/server/0924-Add-drops-to-shear-events.patch index 31dda333409b..e50accc3111c 100644 --- a/patches/server/0924-Add-drops-to-shear-events.patch +++ b/patches/server/0924-Add-drops-to-shear-events.patch @@ -233,15 +233,56 @@ index 2de1a2f666da9db1832907e1651dbff948e37252..5c2ed3c39c8eb850f3be1e2ea5b5a7ea } diff --git a/src/main/java/net/minecraft/world/entity/monster/Bogged.java b/src/main/java/net/minecraft/world/entity/monster/Bogged.java -index 8420d75865b86e1d8afea2527b5521cac184e8b1..6e290d67b00c88ecd2cf2ce5f612f52ebda9e280 100644 +index dc6230458e09f7555eee7f6a567ff60ad454666b..601a1460e92754b05b337d3f53f84ac2d85f09c8 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Bogged.java +++ b/src/main/java/net/minecraft/world/entity/monster/Bogged.java -@@ -135,6 +135,15 @@ public class Bogged extends AbstractSkeleton implements Shearable { +@@ -80,12 +80,19 @@ public class Bogged extends AbstractSkeleton implements Shearable { + + if (itemstack.is(Items.SHEARS) && this.readyForShearing()) { + // CraftBukkit start +- if (!org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand)) { +- this.getEntityData().markDirty(Bogged.DATA_SHEARED); // CraftBukkit - mark dirty to restore sheared state to clients +- return InteractionResult.PASS; ++ // Paper start - expose drops in event ++ java.util.List drops = generateDefaultDrops(); ++ final org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); ++ if (event != null) { ++ if (event.isCancelled()) { ++ this.getEntityData().markDirty(Bogged.DATA_SHEARED); // CraftBukkit - mark dirty to restore sheared state to clients ++ return InteractionResult.PASS; ++ } ++ drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops()); ++ // Paper end - expose drops in event + } + // CraftBukkit end +- this.shear(SoundSource.PLAYERS); ++ this.shear(SoundSource.PLAYERS, drops); // Paper - expose drops in event + this.gameEvent(GameEvent.SHEAR, player); + if (!this.level().isClientSide) { + itemstack.hurtAndBreak(1, player, getSlotForHand(hand)); +@@ -140,12 +147,31 @@ public class Bogged extends AbstractSkeleton implements Shearable { + + @Override + public void shear(SoundSource shearedSoundCategory) { ++ // Paper start - shear drop API ++ this.shear(shearedSoundCategory, generateDefaultDrops()); ++ } ++ ++ @Override ++ public void shear(SoundSource shearedSoundCategory, java.util.List drops) { ++ // Paper end - shear drop API + this.level().playSound((Player) null, (Entity) this, SoundEvents.BOGGED_SHEAR, shearedSoundCategory, 1.0F, 1.0F); +- this.spawnShearedMushrooms(); ++ this.spawnDrops(drops); // Paper - shear drop API + this.setSheared(true); } private void spawnShearedMushrooms() { + // Paper start - shear drops API -+ this.generateShearedMushrooms(stack -> { ++ this.spawnDrops(generateDefaultDrops()); // Only here for people calling spawnSheardMushrooms. Not used otherwise. ++ } ++ private void spawnDrops(java.util.List drops) { ++ drops.forEach(stack -> { + this.forceDrops = true; + this.spawnAtLocation(stack, this.getBbHeight()); + this.forceDrops = false; @@ -249,17 +290,18 @@ index 8420d75865b86e1d8afea2527b5521cac184e8b1..6e290d67b00c88ecd2cf2ce5f612f52e + } + private void generateShearedMushrooms(java.util.function.Consumer stackConsumer) { + // Paper end - shear drops API - if (this.level() instanceof ServerLevel serverLevel) { - LootTable lootTable = serverLevel.getServer().reloadableRegistries().getLootTable(BuiltInLootTables.BOGGED_SHEAR); - LootParams lootParams = new LootParams.Builder(serverLevel) -@@ -143,11 +152,20 @@ public class Bogged extends AbstractSkeleton implements Shearable { - .create(LootContextParamSets.SHEARING); + Level world = this.level(); + + if (world instanceof ServerLevel worldserver) { +@@ -156,12 +182,21 @@ public class Bogged extends AbstractSkeleton implements Shearable { + while (objectlistiterator.hasNext()) { + ItemStack itemstack = (ItemStack) objectlistiterator.next(); - for (ItemStack itemStack : lootTable.getRandomItems(lootParams)) { -- this.spawnAtLocation(itemStack, this.getBbHeight()); -+ stackConsumer.accept(itemStack); // Paper +- this.spawnAtLocation(itemstack, this.getBbHeight()); ++ stackConsumer.accept(itemstack); // Paper } } + } + // Paper start - shear drops API @@ -275,10 +317,10 @@ index 8420d75865b86e1d8afea2527b5521cac184e8b1..6e290d67b00c88ecd2cf2ce5f612f52e public boolean readyForShearing() { return !this.isSheared() && this.isAlive(); diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index bec1f62559b42acee6c955baf7851aecb9179e16..1af662ca881d656b17697fce837f659349241234 100644 +index 1d958323eccd4cf5e369e99e32d2f1dec0959591..56869e0d001d984c6b73f5a92c60508e2366eb61 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1669,20 +1669,20 @@ public class CraftEventFactory { +@@ -1673,20 +1673,20 @@ public class CraftEventFactory { player.level().getCraftServer().getPluginManager().callEvent(event); } diff --git a/patches/server/0925-Add-PlayerShieldDisableEvent.patch b/patches/server/0925-Add-PlayerShieldDisableEvent.patch index 4a3d927625ca..5bbd9b6ff69a 100644 --- a/patches/server/0925-Add-PlayerShieldDisableEvent.patch +++ b/patches/server/0925-Add-PlayerShieldDisableEvent.patch @@ -16,10 +16,10 @@ sideeffects, meaning the disable event cannot share a handlerlist with the cooldown event diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index bef9c905d884fec70f6faecff4d73c5484a412f5..e27fd3a1eb1a128613e328910f09f290007f48d5 100644 +index 454b29d8c9e42e328933aa578f49d28f1e77898a..d0b51d96d6795b5fa03bc195b90324680545b752 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -1004,7 +1004,7 @@ public abstract class Player extends LivingEntity { +@@ -1005,7 +1005,7 @@ public abstract class Player extends LivingEntity { protected void blockUsingShield(LivingEntity attacker) { super.blockUsingShield(attacker); if (attacker.canDisableShield()) { @@ -28,7 +28,7 @@ index bef9c905d884fec70f6faecff4d73c5484a412f5..e27fd3a1eb1a128613e328910f09f290 } } -@@ -1495,8 +1495,21 @@ public abstract class Player extends LivingEntity { +@@ -1498,8 +1498,21 @@ public abstract class Player extends LivingEntity { this.attack(target); } diff --git a/patches/server/0926-Validate-ResourceLocation-in-NBT-reading.patch b/patches/server/0926-Validate-ResourceLocation-in-NBT-reading.patch index 58ef6fe154fe..5531d9ffc8be 100644 --- a/patches/server/0926-Validate-ResourceLocation-in-NBT-reading.patch +++ b/patches/server/0926-Validate-ResourceLocation-in-NBT-reading.patch @@ -66,10 +66,10 @@ index b98f9246b60daf31460f41ce214dfa7c011f5684..842b0cec0397d7ae5166617627340ffa @Nullable diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index a7eec0a1f053d0f4b68604c48aba95420049cfdd..09336e1e21b7bbed7d9730967d5a799c9029332e 100644 +index ff16c7196b146388c526e3100e561be771ca8a91..cbf076c5fa69d32ad3c8ea759cd9d405b60f8663 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -886,11 +886,13 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -887,11 +887,13 @@ public abstract class LivingEntity extends Entity implements Attackable { if (nbt.contains("SleepingX", 99) && nbt.contains("SleepingY", 99) && nbt.contains("SleepingZ", 99)) { BlockPos blockposition = new BlockPos(nbt.getInt("SleepingX"), nbt.getInt("SleepingY"), nbt.getInt("SleepingZ")); diff --git a/patches/server/0928-Fixup-NamespacedKey-handling.patch b/patches/server/0928-Fixup-NamespacedKey-handling.patch index 42c433ad7f3d..2861dc513866 100644 --- a/patches/server/0928-Fixup-NamespacedKey-handling.patch +++ b/patches/server/0928-Fixup-NamespacedKey-handling.patch @@ -85,10 +85,10 @@ index cc97638e038ea64ad180ebfded2528aa07d1809e..10e4318782107644f67818109784fff6 // Now also convert from when keys where saved return CraftRegistry.get(Registry.ATTRIBUTE, key, ApiVersion.CURRENT); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java -index 65a9213ce8197d50a58f94edfd60c25c2be848be..28d8fd2e3eb87e989621ffa6b0e5005bd181391c 100644 +index afed8bdb9bd6a135e9b5f7bd9bfc61964cb240f7..26088d4039599e7bd1ad8017d845e7b1c15be9e1 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBanner.java -@@ -36,7 +36,11 @@ public class CraftBanner extends CraftBlockEntityState implem +@@ -38,7 +38,11 @@ public class CraftBanner extends CraftBlockEntityState implem if (banner.getPatterns() != null) { for (int i = 0; i < banner.getPatterns().layers().size(); i++) { BannerPatternLayers.Layer p = banner.getPatterns().layers().get(i); diff --git a/patches/server/0933-Add-api-for-spawn-egg-texture-colors.patch b/patches/server/0933-Add-api-for-spawn-egg-texture-colors.patch index 2462562bb0a2..0652b1399e4c 100644 --- a/patches/server/0933-Add-api-for-spawn-egg-texture-colors.patch +++ b/patches/server/0933-Add-api-for-spawn-egg-texture-colors.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Add api for spawn egg texture colors diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 17caf21e23aa7f5a5216923e73aae94a59bcac44..3e74e449e5674be3a84168d24f58b108ac334513 100644 +index 278ef7b7cd2cf95dcf38fb4cadfd2acfcc9c4dc5..be009fe105a4fff86d592ebc8df75650aff74a29 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -654,6 +654,15 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -648,6 +648,15 @@ public final class CraftMagicNumbers implements UnsafeValues { return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT); } diff --git a/patches/server/0934-Add-Lifecycle-Event-system.patch b/patches/server/0934-Add-Lifecycle-Event-system.patch index 1b988c3e2545..6c4f2f864410 100644 --- a/patches/server/0934-Add-Lifecycle-Event-system.patch +++ b/patches/server/0934-Add-Lifecycle-Event-system.patch @@ -751,10 +751,10 @@ index d96399e9bf1a58db5a4a22e58abb99e7660e0694..66bdac50130f523f9dc4379b103b7a46 + // Paper end - lifecycle events } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 3e74e449e5674be3a84168d24f58b108ac334513..dabda356cdd4928c306feaace5bf03924b310613 100644 +index be009fe105a4fff86d592ebc8df75650aff74a29..d329da33f9bfea5e30e42cd30974b7d3b775f446 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -663,6 +663,13 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -657,6 +657,13 @@ public final class CraftMagicNumbers implements UnsafeValues { } // Paper end - spawn egg color visibility diff --git a/patches/server/0935-ItemStack-Tooltip-API.patch b/patches/server/0935-ItemStack-Tooltip-API.patch index 6b01a6f3117a..16bb22ce7862 100644 --- a/patches/server/0935-ItemStack-Tooltip-API.patch +++ b/patches/server/0935-ItemStack-Tooltip-API.patch @@ -5,10 +5,10 @@ Subject: [PATCH] ItemStack Tooltip API diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index dabda356cdd4928c306feaace5bf03924b310613..be56e7a7607d3119e560f38e800ad4bbfe1e7714 100644 +index d329da33f9bfea5e30e42cd30974b7d3b775f446..fa60f4e05e3303a7fe4faab0098c1fb439a24354 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -639,6 +639,21 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -633,6 +633,21 @@ public final class CraftMagicNumbers implements UnsafeValues { } // Paper end - fix custom stats criteria creation diff --git a/patches/server/0962-Fix-shield-disable-inconsistency.patch b/patches/server/0962-Fix-shield-disable-inconsistency.patch index 69826053ae63..25f666c8ec01 100644 --- a/patches/server/0962-Fix-shield-disable-inconsistency.patch +++ b/patches/server/0962-Fix-shield-disable-inconsistency.patch @@ -8,10 +8,10 @@ it will not disable the shield if the attacker is holding an axe item. diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 09336e1e21b7bbed7d9730967d5a799c9029332e..fd6b21f7a196e1232c0bb03335bd78417f55c5bb 100644 +index cbf076c5fa69d32ad3c8ea759cd9d405b60f8663..8072d31525d9c7890804bb879893f1a69820e32d 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2325,7 +2325,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2349,7 +2349,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING)); Entity entity = damagesource.getDirectEntity(); diff --git a/patches/server/0967-Fix-helmet-damage-reduction-inconsistencies.patch b/patches/server/0967-Fix-helmet-damage-reduction-inconsistencies.patch index bbce375f3f6c..68b0416c32a7 100644 --- a/patches/server/0967-Fix-helmet-damage-reduction-inconsistencies.patch +++ b/patches/server/0967-Fix-helmet-damage-reduction-inconsistencies.patch @@ -7,13 +7,13 @@ Affect the falling stalactite damage type where the reduction is not applied like in Vanilla diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 37bd0b7a1bfb9d59efa803e453f39d4e3fc916a4..bd6fee3e3ad9116802ff8bb57bfa741b881c4057 100644 +index e9a5f06c405fb81609205b6b96cb0a7e49d5589c..9c7cd9387f90d061aec76f7f0451a1da8b42ea3d 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -1215,7 +1215,7 @@ public class CraftEventFactory { - Map> modifierFunctions = new EnumMap<>(DamageModifier.class); - modifiers.put(DamageModifier.BASE, rawDamage); - modifierFunctions.put(DamageModifier.BASE, CraftEventFactory.ZERO); +@@ -1219,7 +1219,7 @@ public class CraftEventFactory { + modifiers.put(DamageModifier.FREEZING, freezingModifier); + modifierFunctions.put(DamageModifier.FREEZING, freezing); + } - if (source.is(DamageTypes.FALLING_BLOCK) || source.is(DamageTypes.FALLING_ANVIL)) { + if (source.is(DamageTypeTags.DAMAGES_HELMET)) { // Paper modifiers.put(DamageModifier.HARD_HAT, hardHatModifier); diff --git a/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch b/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch index 58c69c8939ac..c6c2190fe5bb 100644 --- a/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch +++ b/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch @@ -5,19 +5,19 @@ Subject: [PATCH] Revert to vanilla handling of LivingEntity#actuallyHurt diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index fd6b21f7a196e1232c0bb03335bd78417f55c5bb..66707853328b6b23771c88abd0cf5a7ef766bb71 100644 +index 8072d31525d9c7890804bb879893f1a69820e32d..de2b1f8e1c9883babe4ded372d51de616d9b44ca 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2210,7 +2210,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2301,7 +2301,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + return CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, freezingModifier, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, freezing, hardHat, blocking, armor, resistance, magic, absorption); } - // CraftBukkit start -- protected boolean actuallyHurt(final DamageSource damagesource, float f) { // void -> boolean, add final -+ protected boolean actuallyHurt(final DamageSource damagesource, float f) { // void -> boolean, add final // Paper - return false ONLY if event cancelled - if (!this.isInvulnerableTo(damagesource)) { - final boolean human = this instanceof net.minecraft.world.entity.player.Player; - float originalDamage = f; -@@ -2382,12 +2382,12 @@ public abstract class LivingEntity extends Entity implements Attackable { +- protected boolean actuallyHurt(final DamageSource damagesource, float f, final EntityDamageEvent event) { // void -> boolean, add final ++ protected boolean actuallyHurt(final DamageSource damagesource, float f, final EntityDamageEvent event) { // void -> boolean, add final // Paper - return false ONLY if event cancelled + if (!this.isInvulnerableTo(damagesource)) { + if (event.isCancelled()) { + return false; +@@ -2411,12 +2411,12 @@ public abstract class LivingEntity extends Entity implements Attackable { return true; } else { diff --git a/patches/server/0969-improve-checking-handled-tags-in-itemmeta.patch b/patches/server/0969-improve-checking-handled-tags-in-itemmeta.patch index ac06baf9f02c..8656622c15f2 100644 --- a/patches/server/0969-improve-checking-handled-tags-in-itemmeta.patch +++ b/patches/server/0969-improve-checking-handled-tags-in-itemmeta.patch @@ -211,7 +211,7 @@ index ef56ebc8060da1d416d91299b03ff0a8f6901ac1..7672128ecca3052f2dc422349a863484 static Material getType(net.minecraft.world.item.ItemStack item) { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java -index 431910368e6d5487456e8430ad7b027d19429b58..9d2feff3df87cfeefe7105d954854af05cef6f69 100644 +index a1f2b9d40d374e8cdbaf916b25fa74b6c0970f81..d03f4a767f6c7fe7d6bcef20e6676c39d9657584 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java @@ -114,8 +114,8 @@ public class CraftItemType implements ItemType.Typed, Han @@ -301,7 +301,7 @@ index 4faada5f974214f3054dc1bec9c79e2600c8df48..d7e5491cc0296563fb9fdf28d64b21a1 getOrEmpty(tag, CraftMetaBlockState.BLOCK_ENTITY_TAG).ifPresent((nbt) -> { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index 4da38ebb7fdbdb0f8fa422ebcd2e3eec2b2be846..a395c7ce952f4a60a5edf80e8731afa6388d18ea 100644 +index 552ebe67f87b48734adf0da8ef78dcac9dd670a2..e064af399dcae40b4f35aa993d356b1462f91d6c 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java @@ -64,8 +64,8 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta, WritableBo @@ -316,7 +316,7 @@ index 4da38ebb7fdbdb0f8fa422ebcd2e3eec2b2be846..a395c7ce952f4a60a5edf80e8731afa6 getOrEmpty(tag, CraftMetaBook.BOOK_CONTENT).ifPresent((writable) -> { List> pages = writable.pages(); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -index c7360e2b2d6e50abc371c21b09cdadd63892f439..3f78a0935d738854182254b345064e3c225dcd5f 100644 +index 162997fc80dfe2df1f13c802c1b610f04cb9d05a..806c1cbee7c4e23eee38c8f400ec2d924c9a360c 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java @@ -78,8 +78,8 @@ public class CraftMetaBookSigned extends CraftMetaItem implements BookMeta { @@ -436,7 +436,7 @@ index 3ff0340c40e9dc9a6e690de15ccade7a0c4e8f02..3f6c5cbbf63631e4b72dc43558651ea9 getOrEmpty(tag, CraftMetaEntityTag.ENTITY_TAG).ifPresent((nbt) -> { this.entityTag = nbt.copyTag(); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java -index f2cecd01f7f214a023e1bdeecc14359f696fb9d4..97b7085250d749c5e46352b372068b51de89bc7f 100644 +index 8c1d2d0521da52f9a1262f5433da21700b9b0454..9600b23666668d7d581e2920a4e03e59cc2339fb 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java @@ -59,8 +59,8 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { @@ -451,7 +451,7 @@ index f2cecd01f7f214a023e1bdeecc14359f696fb9d4..97b7085250d749c5e46352b372068b51 getOrEmpty(tag, CraftMetaFirework.FIREWORKS).ifPresent((fireworks) -> { this.power = fireworks.flightDuration(); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 044713d5b2661405200590914f73b07e73aeb48f..58da8cb19a8444c634cbc1f39e93503ca8e2ecab 100644 +index d29b8c6851aad227eb8f12012903e0ddd5531755..11c6c8d9c14fb31d1819a5c61e3b743b0b6c6d65 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -346,7 +346,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { @@ -463,10 +463,20 @@ index 044713d5b2661405200590914f73b07e73aeb48f..58da8cb19a8444c634cbc1f39e93503c CraftMetaItem.getOrEmpty(tag, CraftMetaItem.NAME).ifPresent((component) -> { this.displayName = component; }); -@@ -457,12 +457,19 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -457,1657 +457,1672 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { }); // Paper end - fix ItemFlags +- Set, Optional>> keys = tag.entrySet(); +- for (Map.Entry, Optional> key : keys) { +- // Paper start - don't lose unhandled tags +- if (key.getValue().isEmpty()) { +- this.unhandledTags.remove(key.getKey()); +- } else if (!CraftMetaItem.getHandledTags().contains(key.getKey())) { +- // Paper end - don't lose unhandled tags +- key.getValue().ifPresent((value) -> { +- this.unhandledTags.set((DataComponentType) key.getKey(), value); +- }); + // Paper start - improve checking handled data component types + Set> handledTags = getTopLevelHandledDcts(this.getClass()); + if (extraHandledTags != null) { @@ -474,20 +484,2835 @@ index 044713d5b2661405200590914f73b07e73aeb48f..58da8cb19a8444c634cbc1f39e93503c + handledTags = extraHandledTags; + } + // Paper end - improve checking handled data component types - Set, Optional>> keys = tag.entrySet(); - for (Map.Entry, Optional> key : keys) { - // Paper start - don't lose unhandled tags - if (key.getValue().isEmpty()) { - this.unhandledTags.remove(key.getKey()); -- } else if (!CraftMetaItem.getHandledTags().contains(key.getKey())) { -+ } else if (!handledTags.contains(key.getKey())) { // Paper - improve checking handled data component types - // Paper end - don't lose unhandled tags - key.getValue().ifPresent((value) -> { - this.unhandledTags.set((DataComponentType) key.getKey(), value); -@@ -2047,68 +2054,75 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - this.version = version; - } ++ Set, Optional>> keys = tag.entrySet(); ++ for (Map.Entry, Optional> key : keys) { ++ // Paper start - don't lose unhandled tags ++ if (key.getValue().isEmpty()) { ++ this.unhandledTags.remove(key.getKey()); ++ } else if (!handledTags.contains(key.getKey())) { // Paper - improve checking handled data component types ++ // Paper end - don't lose unhandled tags ++ key.getValue().ifPresent((value) -> { ++ this.unhandledTags.set((DataComponentType) key.getKey(), value); ++ }); ++ } ++ ++ if (key.getValue().isEmpty()) { ++ this.removedTags.add(key.getKey()); ++ } + } ++ } ++ ++ static EnchantmentMap buildEnchantments(ItemEnchantments tag) { // Paper ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper ++ ++ tag.entrySet().forEach((entry) -> { ++ Holder id = entry.getKey(); ++ int level = entry.getIntValue(); ++ ++ Enchantment enchant = CraftEnchantment.minecraftHolderToBukkit(id); ++ if (enchant != null) { ++ enchantments.put(enchant, level); ++ } ++ }); ++ ++ return enchantments; ++ } ++ ++ static Multimap buildModifiers(ItemAttributeModifiers tag) { ++ Multimap modifiers = LinkedHashMultimap.create(); ++ List mods = tag.modifiers(); ++ int size = mods.size(); ++ ++ for (int i = 0; i < size; i++) { ++ ItemAttributeModifiers.Entry entry = mods.get(i); ++ net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = entry.modifier(); ++ if (nmsModifier == null) { ++ continue; ++ } ++ ++ AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); ++ ++ Attribute attribute = CraftAttribute.minecraftHolderToBukkit(entry.attribute()); ++ if (attribute == null) { ++ continue; ++ } ++ ++ if (entry.slot() != null) { ++ EquipmentSlotGroup slotName = entry.slot(); ++ if (slotName == null) { ++ modifiers.put(attribute, attribMod); ++ continue; ++ } ++ ++ org.bukkit.inventory.EquipmentSlotGroup slot = null; ++ try { ++ slot = CraftEquipmentSlot.getSlot(slotName); ++ } catch (IllegalArgumentException ex) { ++ // SPIGOT-4551 - Slot is invalid, should really match nothing but this is undefined behaviour anyway ++ } ++ ++ if (slot == null) { ++ modifiers.put(attribute, attribMod); ++ continue; ++ } + +- if (key.getValue().isEmpty()) { +- this.removedTags.add(key.getKey()); ++ attribMod = new AttributeModifier(attribMod.getKey(), attribMod.getAmount(), attribMod.getOperation(), slot); ++ } ++ modifiers.put(attribute, attribMod); + } ++ return modifiers; + } +- } + +- static EnchantmentMap buildEnchantments(ItemEnchantments tag) { // Paper +- EnchantmentMap enchantments = new EnchantmentMap(); // Paper ++ CraftMetaItem(Map map) { ++ this.displayName = CraftChatMessage.fromJSONOrString(SerializableMeta.getString(map, CraftMetaItem.NAME.BUKKIT, true), true, false); ++ this.itemName = CraftChatMessage.fromJSONOrNull(SerializableMeta.getString(map, CraftMetaItem.ITEM_NAME.BUKKIT, true)); + +- tag.entrySet().forEach((entry) -> { +- Holder id = entry.getKey(); +- int level = entry.getIntValue(); ++ Iterable lore = SerializableMeta.getObject(Iterable.class, map, CraftMetaItem.LORE.BUKKIT, true); ++ if (lore != null) { ++ CraftMetaItem.safelyAdd(lore, this.lore = new ArrayList(), true); ++ } + +- Enchantment enchant = CraftEnchantment.minecraftHolderToBukkit(id); +- if (enchant != null) { +- enchantments.put(enchant, level); ++ Integer customModelData = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.CUSTOM_MODEL_DATA.BUKKIT, true); ++ if (customModelData != null) { ++ this.setCustomModelData(customModelData); + } +- }); + +- return enchantments; +- } ++ Object blockData = SerializableMeta.getObject(Object.class, map, CraftMetaItem.BLOCK_DATA.BUKKIT, true); ++ if (blockData != null) { ++ Map mapBlockData = new HashMap<>(); + +- static Multimap buildModifiers(ItemAttributeModifiers tag) { +- Multimap modifiers = LinkedHashMultimap.create(); +- List mods = tag.modifiers(); +- int size = mods.size(); ++ CompoundTag nbtBlockData = (CompoundTag) CraftNBTTagConfigSerializer.deserialize(blockData); ++ for (String key : nbtBlockData.getAllKeys()) { ++ mapBlockData.put(key, nbtBlockData.getString(key)); ++ } + +- for (int i = 0; i < size; i++) { +- ItemAttributeModifiers.Entry entry = mods.get(i); +- net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = entry.modifier(); +- if (nmsModifier == null) { +- continue; ++ this.blockData = mapBlockData; + } + +- AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); ++ this.enchantments = CraftMetaItem.buildEnchantments(map, CraftMetaItem.ENCHANTMENTS); ++ this.attributeModifiers = CraftMetaItem.buildModifiers(map, CraftMetaItem.ATTRIBUTES); + +- Attribute attribute = CraftAttribute.minecraftHolderToBukkit(entry.attribute()); +- if (attribute == null) { +- continue; ++ Integer repairCost = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.REPAIR.BUKKIT, true); ++ if (repairCost != null) { ++ this.setRepairCost(repairCost); + } + +- if (entry.slot() != null) { +- EquipmentSlotGroup slotName = entry.slot(); +- if (slotName == null) { +- modifiers.put(attribute, attribMod); +- continue; ++ Iterable hideFlags = SerializableMeta.getObject(Iterable.class, map, CraftMetaItem.HIDEFLAGS.BUKKIT, true); ++ if (hideFlags != null) { ++ for (Object hideFlagObject : hideFlags) { ++ String hideFlagString = (String) hideFlagObject; ++ try { ++ ItemFlag hideFlatEnum = CraftItemFlag.stringToBukkit(hideFlagString); ++ this.addItemFlags(hideFlatEnum); ++ } catch (IllegalArgumentException ex) { ++ // Ignore when we got a old String which does not map to a Enum value anymore ++ } + } ++ } + +- org.bukkit.inventory.EquipmentSlotGroup slot = null; +- try { +- slot = CraftEquipmentSlot.getSlot(slotName); +- } catch (IllegalArgumentException ex) { +- // SPIGOT-4551 - Slot is invalid, should really match nothing but this is undefined behaviour anyway +- } ++ Boolean hideTooltip = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.HIDE_TOOLTIP.BUKKIT, true); ++ if (hideTooltip != null) { ++ this.setHideTooltip(hideTooltip); ++ } + +- if (slot == null) { +- modifiers.put(attribute, attribMod); +- continue; +- } ++ Boolean unbreakable = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.UNBREAKABLE.BUKKIT, true); ++ if (unbreakable != null) { ++ this.setUnbreakable(unbreakable); ++ } + +- attribMod = new AttributeModifier(attribMod.getKey(), attribMod.getAmount(), attribMod.getOperation(), slot); ++ Boolean enchantmentGlintOverride = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.BUKKIT, true); ++ if (enchantmentGlintOverride != null) { ++ this.setEnchantmentGlintOverride(enchantmentGlintOverride); + } +- modifiers.put(attribute, attribMod); +- } +- return modifiers; +- } + +- CraftMetaItem(Map map) { +- this.displayName = CraftChatMessage.fromJSONOrString(SerializableMeta.getString(map, CraftMetaItem.NAME.BUKKIT, true), true, false); +- this.itemName = CraftChatMessage.fromJSONOrNull(SerializableMeta.getString(map, CraftMetaItem.ITEM_NAME.BUKKIT, true)); ++ Boolean fireResistant = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.FIRE_RESISTANT.BUKKIT, true); ++ if (fireResistant != null) { ++ this.setFireResistant(fireResistant); ++ } + +- Iterable lore = SerializableMeta.getObject(Iterable.class, map, CraftMetaItem.LORE.BUKKIT, true); +- if (lore != null) { +- CraftMetaItem.safelyAdd(lore, this.lore = new ArrayList(), true); +- } ++ Integer maxStackSize = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.MAX_STACK_SIZE.BUKKIT, true); ++ if (maxStackSize != null) { ++ this.setMaxStackSize(maxStackSize); ++ } + +- Integer customModelData = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.CUSTOM_MODEL_DATA.BUKKIT, true); +- if (customModelData != null) { +- this.setCustomModelData(customModelData); +- } ++ String rarity = SerializableMeta.getString(map, CraftMetaItem.RARITY.BUKKIT, true); ++ if (rarity != null) { ++ this.setRarity(ItemRarity.valueOf(rarity)); ++ } + +- Object blockData = SerializableMeta.getObject(Object.class, map, CraftMetaItem.BLOCK_DATA.BUKKIT, true); +- if (blockData != null) { +- Map mapBlockData = new HashMap<>(); ++ CraftFoodComponent food = SerializableMeta.getObject(CraftFoodComponent.class, map, CraftMetaItem.FOOD.BUKKIT, true); ++ if (food != null) { ++ this.setFood(food); ++ } + +- CompoundTag nbtBlockData = (CompoundTag) CraftNBTTagConfigSerializer.deserialize(blockData); +- for (String key : nbtBlockData.getAllKeys()) { +- mapBlockData.put(key, nbtBlockData.getString(key)); ++ CraftToolComponent tool = SerializableMeta.getObject(CraftToolComponent.class, map, CraftMetaItem.TOOL.BUKKIT, true); ++ if (tool != null) { ++ this.setTool(tool); + } + +- this.blockData = mapBlockData; +- } ++ CraftJukeboxComponent jukeboxPlayable = SerializableMeta.getObject(CraftJukeboxComponent.class, map, CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, true); ++ if (jukeboxPlayable != null) { ++ this.setJukeboxPlayable(jukeboxPlayable); ++ } + +- this.enchantments = CraftMetaItem.buildEnchantments(map, CraftMetaItem.ENCHANTMENTS); +- this.attributeModifiers = CraftMetaItem.buildModifiers(map, CraftMetaItem.ATTRIBUTES); ++ Integer damage = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.DAMAGE.BUKKIT, true); ++ if (damage != null) { ++ this.setDamage(damage); ++ } + +- Integer repairCost = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.REPAIR.BUKKIT, true); +- if (repairCost != null) { +- this.setRepairCost(repairCost); +- } ++ Integer maxDamage = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.MAX_DAMAGE.BUKKIT, true); ++ if (maxDamage != null) { ++ this.setMaxDamage(maxDamage); ++ } + +- Iterable hideFlags = SerializableMeta.getObject(Iterable.class, map, CraftMetaItem.HIDEFLAGS.BUKKIT, true); +- if (hideFlags != null) { +- for (Object hideFlagObject : hideFlags) { +- String hideFlagString = (String) hideFlagObject; ++ String internal = SerializableMeta.getString(map, "internal", true); ++ if (internal != null) { ++ ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(internal)); + try { +- ItemFlag hideFlatEnum = CraftItemFlag.stringToBukkit(hideFlagString); +- this.addItemFlags(hideFlatEnum); +- } catch (IllegalArgumentException ex) { +- // Ignore when we got a old String which does not map to a Enum value anymore ++ CompoundTag internalTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); ++ this.deserializeInternal(internalTag, map); ++ } catch (IOException ex) { ++ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); + } + } +- } + +- Boolean hideTooltip = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.HIDE_TOOLTIP.BUKKIT, true); +- if (hideTooltip != null) { +- this.setHideTooltip(hideTooltip); +- } ++ String unhandled = SerializableMeta.getString(map, "unhandled", true); ++ if (unhandled != null) { ++ ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(unhandled)); ++ try { ++ CompoundTag unhandledTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); ++ DataComponentPatch unhandledPatch = DataComponentPatch.CODEC.parse(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), unhandledTag).result().get(); ++ // Paper start ++ CraftMetaItem.getOrEmpty(unhandledPatch, CraftMetaItem.CAN_PLACE_ON).ifPresent(data -> { ++ this.canPlaceOnPredicates = List.copyOf(data.predicates); ++ }); ++ CraftMetaItem.getOrEmpty(unhandledPatch, CraftMetaItem.CAN_BREAK).ifPresent(data -> { ++ this.canBreakPredicates = List.copyOf(data.predicates); ++ }); ++ this.unhandledTags.copy(unhandledPatch.forget(type -> type == CraftMetaItem.CAN_PLACE_ON.TYPE || type == CraftMetaItem.CAN_BREAK.TYPE)); ++ // Paper end ++ ++ for (Entry, Optional> entry : unhandledPatch.entrySet()) { ++ // Move removed unhandled tags to dedicated removedTags ++ if (!entry.getValue().isPresent()) { ++ DataComponentType key = entry.getKey(); ++ ++ this.unhandledTags.clear(key); ++ this.removedTags.add(key); ++ } ++ } ++ } catch (IOException ex) { ++ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ } ++ } + +- Boolean unbreakable = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.UNBREAKABLE.BUKKIT, true); +- if (unbreakable != null) { +- this.setUnbreakable(unbreakable); +- } ++ Iterable removed = SerializableMeta.getObject(Iterable.class, map, "removed", true); ++ if (removed != null) { ++ RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); ++ Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); + +- Boolean enchantmentGlintOverride = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.BUKKIT, true); +- if (enchantmentGlintOverride != null) { +- this.setEnchantmentGlintOverride(enchantmentGlintOverride); +- } ++ for (Object removedObject : removed) { ++ String removedString = (String) removedObject; + +- Boolean fireResistant = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.FIRE_RESISTANT.BUKKIT, true); +- if (fireResistant != null) { +- this.setFireResistant(fireResistant); +- } ++ DataComponentType component = componentTypeRegistry.get(ResourceLocation.parse(removedString)); ++ if (component != null) { ++ this.removedTags.add(component); ++ } ++ } ++ } + +- Integer maxStackSize = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.MAX_STACK_SIZE.BUKKIT, true); +- if (maxStackSize != null) { +- this.setMaxStackSize(maxStackSize); +- } ++ Object nbtMap = SerializableMeta.getObject(Object.class, map, CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, true); // We read both legacy maps and potential modern snbt strings here ++ if (nbtMap != null) { ++ this.persistentDataContainer.putAll((CompoundTag) CraftNBTTagConfigSerializer.deserialize(nbtMap)); ++ } + +- String rarity = SerializableMeta.getString(map, CraftMetaItem.RARITY.BUKKIT, true); +- if (rarity != null) { +- this.setRarity(ItemRarity.valueOf(rarity)); ++ String custom = SerializableMeta.getString(map, "custom", true); ++ if (custom != null) { ++ ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(custom)); ++ try { ++ this.customTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); ++ } catch (IOException ex) { ++ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ } ++ } + } + +- CraftFoodComponent food = SerializableMeta.getObject(CraftFoodComponent.class, map, CraftMetaItem.FOOD.BUKKIT, true); +- if (food != null) { +- this.setFood(food); ++ void deserializeInternal(CompoundTag tag, Object context) { ++ // SPIGOT-4576: Need to migrate from internal to proper data ++ if (tag.contains(CraftMetaItem.ATTRIBUTES.NBT, CraftMagicNumbers.NBT.TAG_LIST)) { ++ this.attributeModifiers = CraftMetaItem.buildModifiersLegacy(tag, CraftMetaItem.ATTRIBUTES); ++ } + } + +- CraftToolComponent tool = SerializableMeta.getObject(CraftToolComponent.class, map, CraftMetaItem.TOOL.BUKKIT, true); +- if (tool != null) { +- this.setTool(tool); +- } ++ private static Multimap buildModifiersLegacy(CompoundTag tag, ItemMetaKey key) { ++ Multimap modifiers = LinkedHashMultimap.create(); ++ if (!tag.contains(key.NBT, CraftMagicNumbers.NBT.TAG_LIST)) { ++ return modifiers; ++ } ++ ListTag mods = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); ++ int size = mods.size(); + +- CraftJukeboxComponent jukeboxPlayable = SerializableMeta.getObject(CraftJukeboxComponent.class, map, CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, true); +- if (jukeboxPlayable != null) { +- this.setJukeboxPlayable(jukeboxPlayable); +- } ++ for (int i = 0; i < size; i++) { ++ CompoundTag entry = mods.getCompound(i); ++ if (entry.isEmpty()) { ++ // entry is not an actual NBTTagCompound. getCompound returns empty NBTTagCompound in that case ++ continue; ++ } ++ net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = net.minecraft.world.entity.ai.attributes.AttributeModifier.load(entry); ++ if (nmsModifier == null) { ++ continue; ++ } + +- Integer damage = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.DAMAGE.BUKKIT, true); +- if (damage != null) { +- this.setDamage(damage); +- } ++ AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); + +- Integer maxDamage = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.MAX_DAMAGE.BUKKIT, true); +- if (maxDamage != null) { +- this.setMaxDamage(maxDamage); ++ String attributeName = org.bukkit.craftbukkit.attribute.CraftAttributeMap.convertIfNeeded(entry.getString(CraftMetaItem.ATTRIBUTES_IDENTIFIER.NBT)); // Paper ++ if (attributeName == null || attributeName.isEmpty()) { ++ continue; ++ } ++ ++ Attribute attribute = CraftAttribute.stringToBukkit(attributeName); ++ if (attribute == null) { ++ continue; ++ } ++ ++ if (entry.contains(CraftMetaItem.ATTRIBUTES_SLOT.NBT, CraftMagicNumbers.NBT.TAG_STRING)) { ++ String slotName = entry.getString(CraftMetaItem.ATTRIBUTES_SLOT.NBT); ++ if (slotName == null || slotName.isEmpty()) { ++ modifiers.put(attribute, attribMod); ++ continue; ++ } ++ ++ EquipmentSlot slot = null; ++ try { ++ slot = CraftEquipmentSlot.getSlot(net.minecraft.world.entity.EquipmentSlot.byName(slotName.toLowerCase(Locale.ROOT))); ++ } catch (IllegalArgumentException ex) { ++ // SPIGOT-4551 - Slot is invalid, should really match nothing but this is undefined behaviour anyway ++ } ++ ++ if (slot == null) { ++ modifiers.put(attribute, attribMod); ++ continue; ++ } ++ ++ attribMod = new AttributeModifier(attribMod.getKey(), attribMod.getAmount(), attribMod.getOperation(), slot.getGroup()); ++ } ++ modifiers.put(attribute, attribMod); ++ } ++ return modifiers; + } + +- String internal = SerializableMeta.getString(map, "internal", true); +- if (internal != null) { +- ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(internal)); +- try { +- CompoundTag internalTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); +- this.deserializeInternal(internalTag, map); +- } catch (IOException ex) { +- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper ++ Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); ++ if (ench == null) { ++ return null; ++ } ++ ++ EnchantmentMap enchantments = new EnchantmentMap(); // Paper ++ for (Map.Entry entry : ench.entrySet()) { ++ Enchantment enchantment = CraftEnchantment.stringToBukkit(entry.getKey().toString()); ++ if ((enchantment != null) && (entry.getValue() instanceof Integer)) { ++ enchantments.put(enchantment, (Integer) entry.getValue()); ++ } + } ++ ++ return enchantments; + } + +- String unhandled = SerializableMeta.getString(map, "unhandled", true); +- if (unhandled != null) { +- ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(unhandled)); +- try { +- CompoundTag unhandledTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); +- DataComponentPatch unhandledPatch = DataComponentPatch.CODEC.parse(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), unhandledTag).result().get(); +- // Paper start +- CraftMetaItem.getOrEmpty(unhandledPatch, CraftMetaItem.CAN_PLACE_ON).ifPresent(data -> { +- this.canPlaceOnPredicates = List.copyOf(data.predicates); +- }); +- CraftMetaItem.getOrEmpty(unhandledPatch, CraftMetaItem.CAN_BREAK).ifPresent(data -> { +- this.canBreakPredicates = List.copyOf(data.predicates); +- }); +- this.unhandledTags.copy(unhandledPatch.forget(type -> type == CraftMetaItem.CAN_PLACE_ON.TYPE || type == CraftMetaItem.CAN_BREAK.TYPE)); +- // Paper end ++ static Multimap buildModifiers(Map map, ItemMetaKey key) { ++ Map mods = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); ++ Multimap result = LinkedHashMultimap.create(); ++ if (mods == null) { ++ return result; ++ } + +- for (Entry, Optional> entry : unhandledPatch.entrySet()) { +- // Move removed unhandled tags to dedicated removedTags +- if (!entry.getValue().isPresent()) { +- DataComponentType key = entry.getKey(); ++ for (Object obj : mods.keySet()) { ++ if (!(obj instanceof String)) { ++ continue; ++ } ++ String attributeName = (String) obj; ++ if (Strings.isNullOrEmpty(attributeName)) { ++ continue; ++ } ++ List list = SerializableMeta.getObject(List.class, mods, attributeName, true); ++ if (list == null || list.isEmpty()) { ++ return result; ++ } + +- this.unhandledTags.clear(key); +- this.removedTags.add(key); ++ for (Object o : list) { ++ if (!(o instanceof AttributeModifier)) { // this catches null ++ continue; + } ++ AttributeModifier modifier = (AttributeModifier) o; ++ Attribute attribute = CraftAttribute.stringToBukkit(attributeName); ++ if (attribute == null) { ++ continue; ++ } ++ ++ result.put(attribute, modifier); + } +- } catch (IOException ex) { +- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); + } ++ return result; + } + +- Iterable removed = SerializableMeta.getObject(Iterable.class, map, "removed", true); +- if (removed != null) { +- RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); +- Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); ++ @Overridden ++ void applyToItem(CraftMetaItem.Applicator itemTag) { ++ if (this.hasDisplayName()) { ++ itemTag.put(CraftMetaItem.NAME, this.displayName); ++ } ++ ++ if (this.hasItemName()) { ++ itemTag.put(CraftMetaItem.ITEM_NAME, this.itemName); ++ } + +- for (Object removedObject : removed) { +- String removedString = (String) removedObject; ++ if (this.lore != null) { ++ itemTag.put(CraftMetaItem.LORE, new ItemLore(this.lore)); ++ } ++ ++ if (this.hasCustomModelData()) { ++ itemTag.put(CraftMetaItem.CUSTOM_MODEL_DATA, new CustomModelData(this.customModelData)); ++ } + +- DataComponentType component = componentTypeRegistry.get(ResourceLocation.parse(removedString)); +- if (component != null) { +- this.removedTags.add(component); ++ if (this.hasBlockData()) { ++ itemTag.put(CraftMetaItem.BLOCK_DATA, new BlockItemStateProperties(this.blockData)); ++ } ++ ++ if (this.hideFlag != 0) { ++ if (this.hasItemFlag(ItemFlag.HIDE_ADDITIONAL_TOOLTIP)) { ++ itemTag.put(CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP, Unit.INSTANCE); + } + } +- } + +- Object nbtMap = SerializableMeta.getObject(Object.class, map, CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, true); // We read both legacy maps and potential modern snbt strings here +- if (nbtMap != null) { +- this.persistentDataContainer.putAll((CompoundTag) CraftNBTTagConfigSerializer.deserialize(nbtMap)); +- } ++ this.applyEnchantments(this.enchantments, itemTag, CraftMetaItem.ENCHANTMENTS, ItemFlag.HIDE_ENCHANTS); ++ this.applyModifiers(this.attributeModifiers, itemTag); + +- String custom = SerializableMeta.getString(map, "custom", true); +- if (custom != null) { +- ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(custom)); +- try { +- this.customTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); +- } catch (IOException ex) { +- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ if (this.hasRepairCost()) { ++ itemTag.put(CraftMetaItem.REPAIR, this.repairCost); + } +- } +- } + +- void deserializeInternal(CompoundTag tag, Object context) { +- // SPIGOT-4576: Need to migrate from internal to proper data +- if (tag.contains(CraftMetaItem.ATTRIBUTES.NBT, CraftMagicNumbers.NBT.TAG_LIST)) { +- this.attributeModifiers = CraftMetaItem.buildModifiersLegacy(tag, CraftMetaItem.ATTRIBUTES); +- } +- } ++ if (this.isHideTooltip()) { ++ itemTag.put(CraftMetaItem.HIDE_TOOLTIP, Unit.INSTANCE); ++ } + +- private static Multimap buildModifiersLegacy(CompoundTag tag, ItemMetaKey key) { +- Multimap modifiers = LinkedHashMultimap.create(); +- if (!tag.contains(key.NBT, CraftMagicNumbers.NBT.TAG_LIST)) { +- return modifiers; +- } +- ListTag mods = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); +- int size = mods.size(); ++ if (this.isUnbreakable()) { ++ itemTag.put(CraftMetaItem.UNBREAKABLE, new Unbreakable(!this.hasItemFlag(ItemFlag.HIDE_UNBREAKABLE))); ++ } + +- for (int i = 0; i < size; i++) { +- CompoundTag entry = mods.getCompound(i); +- if (entry.isEmpty()) { +- // entry is not an actual NBTTagCompound. getCompound returns empty NBTTagCompound in that case +- continue; ++ if (this.hasEnchantmentGlintOverride()) { ++ itemTag.put(CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE, this.getEnchantmentGlintOverride()); + } +- net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = net.minecraft.world.entity.ai.attributes.AttributeModifier.load(entry); +- if (nmsModifier == null) { +- continue; ++ ++ if (this.isFireResistant()) { ++ itemTag.put(CraftMetaItem.FIRE_RESISTANT, Unit.INSTANCE); + } + +- AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); ++ if (this.hasMaxStackSize()) { ++ itemTag.put(CraftMetaItem.MAX_STACK_SIZE, this.maxStackSize); ++ } + +- String attributeName = org.bukkit.craftbukkit.attribute.CraftAttributeMap.convertIfNeeded(entry.getString(CraftMetaItem.ATTRIBUTES_IDENTIFIER.NBT)); // Paper +- if (attributeName == null || attributeName.isEmpty()) { +- continue; ++ if (this.hasRarity()) { ++ itemTag.put(CraftMetaItem.RARITY, Rarity.valueOf(this.rarity.name())); + } + +- Attribute attribute = CraftAttribute.stringToBukkit(attributeName); +- if (attribute == null) { +- continue; ++ if (this.hasFood()) { ++ itemTag.put(CraftMetaItem.FOOD, this.food.getHandle()); + } + +- if (entry.contains(CraftMetaItem.ATTRIBUTES_SLOT.NBT, CraftMagicNumbers.NBT.TAG_STRING)) { +- String slotName = entry.getString(CraftMetaItem.ATTRIBUTES_SLOT.NBT); +- if (slotName == null || slotName.isEmpty()) { +- modifiers.put(attribute, attribMod); +- continue; +- } ++ if (this.hasTool()) { ++ itemTag.put(CraftMetaItem.TOOL, this.tool.getHandle()); ++ } + +- EquipmentSlot slot = null; +- try { +- slot = CraftEquipmentSlot.getSlot(net.minecraft.world.entity.EquipmentSlot.byName(slotName.toLowerCase(Locale.ROOT))); +- } catch (IllegalArgumentException ex) { +- // SPIGOT-4551 - Slot is invalid, should really match nothing but this is undefined behaviour anyway ++ if (this.hasJukeboxPlayable()) { ++ itemTag.put(CraftMetaItem.JUKEBOX_PLAYABLE, this.jukebox.getHandle()); ++ } ++ ++ if (this.hasDamage()) { ++ itemTag.put(CraftMetaItem.DAMAGE, this.damage); ++ } ++ ++ if (this.hasMaxDamage()) { ++ itemTag.put(CraftMetaItem.MAX_DAMAGE, this.maxDamage); ++ } ++ ++ // Paper start ++ if (this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty()) { ++ itemTag.put(CraftMetaItem.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON))); ++ } ++ if (this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty()) { ++ itemTag.put(CraftMetaItem.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS))); ++ } ++ // Paper end ++ ++ for (Map.Entry, Optional> e : this.unhandledTags.build().entrySet()) { ++ e.getValue().ifPresentOrElse((value) -> { ++ itemTag.builder.set((DataComponentType) e.getKey(), value); ++ }, () -> itemTag.remove(e.getKey())); ++ } ++ ++ for (DataComponentType removed : this.removedTags) { ++ if (!itemTag.builder.isSet(removed)) { ++ itemTag.builder.remove(removed); + } ++ } + +- if (slot == null) { +- modifiers.put(attribute, attribMod); +- continue; ++ CompoundTag customTag = (this.customTag != null) ? this.customTag.copy() : null; ++ if (!this.persistentDataContainer.isEmpty()) { ++ CompoundTag bukkitCustomCompound = new CompoundTag(); ++ Map rawPublicMap = this.persistentDataContainer.getRaw(); ++ ++ for (Map.Entry nbtBaseEntry : rawPublicMap.entrySet()) { ++ bukkitCustomCompound.put(nbtBaseEntry.getKey(), nbtBaseEntry.getValue()); + } + +- attribMod = new AttributeModifier(attribMod.getKey(), attribMod.getAmount(), attribMod.getOperation(), slot.getGroup()); ++ if (customTag == null) { ++ customTag = new CompoundTag(); ++ } ++ customTag.put(CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, bukkitCustomCompound); + } +- modifiers.put(attribute, attribMod); +- } +- return modifiers; +- } + +- static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper +- Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); +- if (ench == null) { +- return null; ++ if (customTag != null) { ++ itemTag.put(CraftMetaItem.CUSTOM_DATA, CustomData.of(customTag)); ++ } + } + +- EnchantmentMap enchantments = new EnchantmentMap(); // Paper +- for (Map.Entry entry : ench.entrySet()) { +- Enchantment enchantment = CraftEnchantment.stringToBukkit(entry.getKey().toString()); +- if ((enchantment != null) && (entry.getValue() instanceof Integer)) { +- enchantments.put(enchantment, (Integer) entry.getValue()); ++ void applyEnchantments(Map enchantments, CraftMetaItem.Applicator tag, ItemMetaKeyType key, ItemFlag itemFlag) { ++ if (enchantments == null) { ++ return; + } +- } + +- return enchantments; +- } ++ ItemEnchantments.Mutable list = new ItemEnchantments.Mutable(ItemEnchantments.EMPTY); + +- static Multimap buildModifiers(Map map, ItemMetaKey key) { +- Map mods = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); +- Multimap result = LinkedHashMultimap.create(); +- if (mods == null) { +- return result; ++ for (Map.Entry entry : enchantments.entrySet()) { ++ list.set(CraftEnchantment.bukkitToMinecraftHolder(entry.getKey()), entry.getValue()); ++ } ++ ++ list.showInTooltip = !this.hasItemFlag(itemFlag); ++ tag.put(key, list.toImmutable()); + } + +- for (Object obj : mods.keySet()) { +- if (!(obj instanceof String)) { +- continue; +- } +- String attributeName = (String) obj; +- if (Strings.isNullOrEmpty(attributeName)) { +- continue; +- } +- List list = SerializableMeta.getObject(List.class, mods, attributeName, true); +- if (list == null || list.isEmpty()) { +- return result; ++ void applyModifiers(Multimap modifiers, CraftMetaItem.Applicator tag) { ++ if (modifiers == null || modifiers.isEmpty()) { ++ if (this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES)) { ++ tag.put(CraftMetaItem.ATTRIBUTES, new ItemAttributeModifiers(Collections.emptyList(), false)); ++ } ++ return; + } + +- for (Object o : list) { +- if (!(o instanceof AttributeModifier)) { // this catches null ++ ItemAttributeModifiers.Builder list = ItemAttributeModifiers.builder(); ++ for (Map.Entry entry : modifiers.entries()) { ++ if (entry.getKey() == null || entry.getValue() == null) { + continue; + } +- AttributeModifier modifier = (AttributeModifier) o; +- Attribute attribute = CraftAttribute.stringToBukkit(attributeName); +- if (attribute == null) { ++ net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = CraftAttributeInstance.convert(entry.getValue()); ++ ++ Holder name = CraftAttribute.bukkitToMinecraftHolder(entry.getKey()); ++ if (name == null) { + continue; + } + +- result.put(attribute, modifier); ++ EquipmentSlotGroup group = CraftEquipmentSlot.getNMSGroup(entry.getValue().getSlotGroup()); ++ list.add(name, nmsModifier, group); + } ++ tag.put(CraftMetaItem.ATTRIBUTES, list.build().withTooltip(!this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES))); + } +- return result; +- } + +- @Overridden +- void applyToItem(CraftMetaItem.Applicator itemTag) { +- if (this.hasDisplayName()) { +- itemTag.put(CraftMetaItem.NAME, this.displayName); +- } ++ boolean applicableTo(Material type) { ++ if (type == Material.AIR || !type.isItem()) { ++ return false; ++ } + +- if (this.hasItemName()) { +- itemTag.put(CraftMetaItem.ITEM_NAME, this.itemName); +- } ++ if (this.getClass() == CraftMetaItem.class) { ++ return true; ++ } + +- if (this.lore != null) { +- itemTag.put(CraftMetaItem.LORE, new ItemLore(this.lore)); ++ // We assume that the corresponding bukkit interface is always the first one ++ return type.asItemType().getItemMetaClass() == this.getClass().getInterfaces()[0]; + } + +- if (this.hasCustomModelData()) { +- itemTag.put(CraftMetaItem.CUSTOM_MODEL_DATA, new CustomModelData(this.customModelData)); ++ @Overridden ++ boolean isEmpty() { ++ return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper + } + +- if (this.hasBlockData()) { +- itemTag.put(CraftMetaItem.BLOCK_DATA, new BlockItemStateProperties(this.blockData)); ++ // Paper start ++ @Override ++ public net.kyori.adventure.text.Component displayName() { ++ return displayName == null ? null : io.papermc.paper.adventure.PaperAdventure.asAdventure(displayName); + } + +- if (this.hideFlag != 0) { +- if (this.hasItemFlag(ItemFlag.HIDE_ADDITIONAL_TOOLTIP)) { +- itemTag.put(CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP, Unit.INSTANCE); +- } ++ @Override ++ public void displayName(final net.kyori.adventure.text.Component displayName) { ++ this.displayName = displayName == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName); + } ++ // Paper end + +- this.applyEnchantments(this.enchantments, itemTag, CraftMetaItem.ENCHANTMENTS, ItemFlag.HIDE_ENCHANTS); +- this.applyModifiers(this.attributeModifiers, itemTag); +- +- if (this.hasRepairCost()) { +- itemTag.put(CraftMetaItem.REPAIR, this.repairCost); ++ @Override ++ public String getDisplayName() { ++ return CraftChatMessage.fromComponent(this.displayName); + } + +- if (this.isHideTooltip()) { +- itemTag.put(CraftMetaItem.HIDE_TOOLTIP, Unit.INSTANCE); ++ // Paper start ++ @Override ++ public net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent() { ++ return displayName == null ? new net.md_5.bungee.api.chat.BaseComponent[0] : net.md_5.bungee.chat.ComponentSerializer.parse(CraftChatMessage.toJSON(displayName)); ++ } ++ // Paper end ++ @Override ++ public final void setDisplayName(String name) { ++ this.displayName = CraftChatMessage.fromStringOrNull(name); + } + +- if (this.isUnbreakable()) { +- itemTag.put(CraftMetaItem.UNBREAKABLE, new Unbreakable(!this.hasItemFlag(ItemFlag.HIDE_UNBREAKABLE))); ++ // Paper start ++ @Override ++ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { ++ this.displayName = CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(component)); ++ } ++ // Paper end ++ @Override ++ public boolean hasDisplayName() { ++ return this.displayName != null; + } + +- if (this.hasEnchantmentGlintOverride()) { +- itemTag.put(CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE, this.getEnchantmentGlintOverride()); ++ @Override ++ public String getItemName() { ++ return CraftChatMessage.fromComponent(this.itemName); + } + +- if (this.isFireResistant()) { +- itemTag.put(CraftMetaItem.FIRE_RESISTANT, Unit.INSTANCE); ++ @Override ++ public final void setItemName(String name) { ++ this.itemName = CraftChatMessage.fromStringOrNull(name); + } + +- if (this.hasMaxStackSize()) { +- itemTag.put(CraftMetaItem.MAX_STACK_SIZE, this.maxStackSize); ++ @Override ++ public boolean hasItemName() { ++ return this.itemName != null; + } + +- if (this.hasRarity()) { +- itemTag.put(CraftMetaItem.RARITY, Rarity.valueOf(this.rarity.name())); ++ // Paper start - Adventure ++ @Override ++ public net.kyori.adventure.text.Component itemName() { ++ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.itemName); + } + +- if (this.hasFood()) { +- itemTag.put(CraftMetaItem.FOOD, this.food.getHandle()); ++ @Override ++ public void itemName(final net.kyori.adventure.text.Component name) { ++ this.itemName = io.papermc.paper.adventure.PaperAdventure.asVanilla(name); + } ++ // Paper end - Adventure + +- if (this.hasTool()) { +- itemTag.put(CraftMetaItem.TOOL, this.tool.getHandle()); ++ @Override ++ public String getLocalizedName() { ++ return this.getDisplayName(); + } + +- if (this.hasJukeboxPlayable()) { +- itemTag.put(CraftMetaItem.JUKEBOX_PLAYABLE, this.jukebox.getHandle()); ++ @Override ++ public void setLocalizedName(String name) { + } + +- if (this.hasDamage()) { +- itemTag.put(CraftMetaItem.DAMAGE, this.damage); ++ @Override ++ public boolean hasLocalizedName() { ++ return false; + } + +- if (this.hasMaxDamage()) { +- itemTag.put(CraftMetaItem.MAX_DAMAGE, this.maxDamage); ++ @Override ++ public boolean hasLore() { ++ return this.lore != null && !this.lore.isEmpty(); + } + + // Paper start +- if (this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty()) { +- itemTag.put(CraftMetaItem.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON))); ++ @Override ++ public List lore() { ++ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(this.lore) : null; + } +- if (this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty()) { +- itemTag.put(CraftMetaItem.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS))); ++ ++ @Override ++ public void lore(final List lore) { ++ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(lore) : null; + } + // Paper end + +- for (Map.Entry, Optional> e : this.unhandledTags.build().entrySet()) { +- e.getValue().ifPresentOrElse((value) -> { +- itemTag.builder.set((DataComponentType) e.getKey(), value); +- }, () -> itemTag.remove(e.getKey())); ++ @Override ++ public boolean hasRepairCost() { ++ return this.repairCost > 0; ++ } ++ ++ @Override ++ public boolean hasEnchant(Enchantment ench) { ++ Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); ++ return this.hasEnchants() && this.enchantments.containsKey(ench); + } + +- for (DataComponentType removed : this.removedTags) { +- if (!itemTag.builder.isSet(removed)) { +- itemTag.builder.remove(removed); ++ @Override ++ public int getEnchantLevel(Enchantment ench) { ++ Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); ++ Integer level = this.hasEnchants() ? this.enchantments.get(ench) : null; ++ if (level == null) { ++ return 0; + } ++ return level; + } + +- CompoundTag customTag = (this.customTag != null) ? this.customTag.copy() : null; +- if (!this.persistentDataContainer.isEmpty()) { +- CompoundTag bukkitCustomCompound = new CompoundTag(); +- Map rawPublicMap = this.persistentDataContainer.getRaw(); ++ @Override ++ public Map getEnchants() { ++ return this.hasEnchants() ? ImmutableSortedMap.copyOfSorted(this.enchantments) : ImmutableMap.of(); // Paper ++ } + +- for (Map.Entry nbtBaseEntry : rawPublicMap.entrySet()) { +- bukkitCustomCompound.put(nbtBaseEntry.getKey(), nbtBaseEntry.getValue()); ++ @Override ++ public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { ++ Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); ++ if (this.enchantments == null) { ++ this.enchantments = new EnchantmentMap(); // Paper + } + +- if (customTag == null) { +- customTag = new CompoundTag(); ++ if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { ++ Integer old = this.enchantments.put(ench, level); ++ return old == null || old != level; + } +- customTag.put(CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, bukkitCustomCompound); ++ return false; + } + +- if (customTag != null) { +- itemTag.put(CraftMetaItem.CUSTOM_DATA, CustomData.of(customTag)); ++ @Override ++ public boolean removeEnchant(Enchantment ench) { ++ Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); ++ boolean enchantmentRemoved = this.hasEnchants() && this.enchantments.remove(ench) != null; ++ // If we no longer have any enchantments, then clear enchantment tag ++ if (enchantmentRemoved && this.enchantments.isEmpty()) { ++ this.enchantments = null; ++ } ++ return enchantmentRemoved; + } +- } + +- void applyEnchantments(Map enchantments, CraftMetaItem.Applicator tag, ItemMetaKeyType key, ItemFlag itemFlag) { +- if (enchantments == null) { +- return; ++ @Override ++ public void removeEnchantments() { ++ if (this.hasEnchants()) { ++ this.enchantments.clear(); ++ } + } + +- ItemEnchantments.Mutable list = new ItemEnchantments.Mutable(ItemEnchantments.EMPTY); +- +- for (Map.Entry entry : enchantments.entrySet()) { +- list.set(CraftEnchantment.bukkitToMinecraftHolder(entry.getKey()), entry.getValue()); ++ @Override ++ public boolean hasEnchants() { ++ return !(this.enchantments == null || this.enchantments.isEmpty()); + } + +- list.showInTooltip = !this.hasItemFlag(itemFlag); +- tag.put(key, list.toImmutable()); +- } ++ @Override ++ public boolean hasConflictingEnchant(Enchantment ench) { ++ return CraftMetaItem.checkConflictingEnchants(this.enchantments, ench); ++ } + +- void applyModifiers(Multimap modifiers, CraftMetaItem.Applicator tag) { +- if (modifiers == null || modifiers.isEmpty()) { +- if (this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES)) { +- tag.put(CraftMetaItem.ATTRIBUTES, new ItemAttributeModifiers(Collections.emptyList(), false)); ++ @Override ++ public void addItemFlags(ItemFlag... hideFlags) { ++ for (ItemFlag f : hideFlags) { ++ this.hideFlag |= this.getBitModifier(f); + } +- return; + } + +- ItemAttributeModifiers.Builder list = ItemAttributeModifiers.builder(); +- for (Map.Entry entry : modifiers.entries()) { +- if (entry.getKey() == null || entry.getValue() == null) { +- continue; ++ @Override ++ public void removeItemFlags(ItemFlag... hideFlags) { ++ for (ItemFlag f : hideFlags) { ++ this.hideFlag &= ~this.getBitModifier(f); + } +- net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = CraftAttributeInstance.convert(entry.getValue()); ++ } ++ ++ @Override ++ public Set getItemFlags() { ++ Set currentFlags = EnumSet.noneOf(ItemFlag.class); + +- Holder name = CraftAttribute.bukkitToMinecraftHolder(entry.getKey()); +- if (name == null) { +- continue; ++ for (ItemFlag f : ItemFlag.values()) { ++ if (this.hasItemFlag(f)) { ++ currentFlags.add(f); ++ } + } + +- EquipmentSlotGroup group = CraftEquipmentSlot.getNMSGroup(entry.getValue().getSlotGroup()); +- list.add(name, nmsModifier, group); ++ return currentFlags; + } +- tag.put(CraftMetaItem.ATTRIBUTES, list.build().withTooltip(!this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES))); +- } + +- boolean applicableTo(Material type) { +- if (type == Material.AIR || !type.isItem()) { +- return false; ++ @Override ++ public boolean hasItemFlag(ItemFlag flag) { ++ int bitModifier = this.getBitModifier(flag); ++ return (this.hideFlag & bitModifier) == bitModifier; + } + +- if (this.getClass() == CraftMetaItem.class) { +- return true; ++ private int getBitModifier(ItemFlag hideFlag) { ++ return 1 << hideFlag.ordinal(); + } +- // We assume that the corresponding bukkit interface is always the first one +- return type.asItemType().getItemMetaClass() == this.getClass().getInterfaces()[0]; +- } ++ @Override ++ public List getLore() { ++ return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromComponent)); ++ } + +- @Overridden +- boolean isEmpty() { +- return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper +- } ++ // Paper start ++ @Override ++ public List getLoreComponents() { ++ return this.lore == null ? null : new ArrayList<>(this.lore.stream().map(entry -> ++ net.md_5.bungee.chat.ComponentSerializer.parse(CraftChatMessage.toJSON(entry)) ++ ).collect(java.util.stream.Collectors.toList())); ++ } ++ // Paper end ++ @Override ++ public void setLore(List lore) { ++ if (lore == null || lore.isEmpty()) { ++ this.lore = null; ++ } else { ++ if (this.lore == null) { ++ this.lore = new ArrayList(lore.size()); ++ } else { ++ this.lore.clear(); ++ } ++ CraftMetaItem.safelyAdd(lore, this.lore, false); ++ } ++ } + +- // Paper start +- @Override +- public net.kyori.adventure.text.Component displayName() { +- return displayName == null ? null : io.papermc.paper.adventure.PaperAdventure.asAdventure(displayName); +- } ++ // Paper start ++ @Override ++ public void setLoreComponents(List lore) { ++ if (lore == null) { ++ this.lore = null; ++ } else { ++ if (this.lore == null) { ++ safelyAdd(lore, this.lore = new ArrayList<>(lore.size()), false); ++ } else { ++ this.lore.clear(); ++ safelyAdd(lore, this.lore, false); ++ } ++ } ++ } ++ // Paper end ++ @Override ++ public boolean hasCustomModelData() { ++ return this.customModelData != null; ++ } + +- @Override +- public void displayName(final net.kyori.adventure.text.Component displayName) { +- this.displayName = displayName == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName); +- } +- // Paper end ++ @Override ++ public int getCustomModelData() { ++ Preconditions.checkState(this.hasCustomModelData(), "We don't have CustomModelData! Check hasCustomModelData first!"); ++ return this.customModelData; ++ } + +- @Override +- public String getDisplayName() { +- return CraftChatMessage.fromComponent(this.displayName); +- } ++ @Override ++ public void setCustomModelData(Integer data) { ++ this.customModelData = data; ++ } + +- // Paper start +- @Override +- public net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent() { +- return displayName == null ? new net.md_5.bungee.api.chat.BaseComponent[0] : net.md_5.bungee.chat.ComponentSerializer.parse(CraftChatMessage.toJSON(displayName)); +- } +- // Paper end +- @Override +- public final void setDisplayName(String name) { +- this.displayName = CraftChatMessage.fromStringOrNull(name); +- } ++ @Override ++ public boolean hasBlockData() { ++ return this.blockData != null; ++ } + +- // Paper start +- @Override +- public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { +- this.displayName = CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(component)); +- } +- // Paper end +- @Override +- public boolean hasDisplayName() { +- return this.displayName != null; +- } ++ @Override ++ public BlockData getBlockData(Material material) { ++ BlockState defaultData = CraftBlockType.bukkitToMinecraft(material).defaultBlockState(); ++ return CraftBlockData.fromData((this.hasBlockData()) ? new BlockItemStateProperties(this.blockData).apply(defaultData) : defaultData); ++ } + +- @Override +- public String getItemName() { +- return CraftChatMessage.fromComponent(this.itemName); +- } ++ @Override ++ public void setBlockData(BlockData blockData) { ++ this.blockData = (blockData == null) ? null : ((CraftBlockData) blockData).toStates(); ++ } + +- @Override +- public final void setItemName(String name) { +- this.itemName = CraftChatMessage.fromStringOrNull(name); +- } ++ @Override ++ public int getRepairCost() { ++ return this.repairCost; ++ } + +- @Override +- public boolean hasItemName() { +- return this.itemName != null; +- } ++ @Override ++ public void setRepairCost(int cost) { // TODO: Does this have limits? ++ this.repairCost = cost; ++ } + +- // Paper start - Adventure +- @Override +- public net.kyori.adventure.text.Component itemName() { +- return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.itemName); +- } ++ @Override ++ public boolean isHideTooltip() { ++ return this.hideTooltip; ++ } + +- @Override +- public void itemName(final net.kyori.adventure.text.Component name) { +- this.itemName = io.papermc.paper.adventure.PaperAdventure.asVanilla(name); +- } +- // Paper end - Adventure ++ @Override ++ public void setHideTooltip(boolean hideTooltip) { ++ this.hideTooltip = hideTooltip; ++ } + +- @Override +- public String getLocalizedName() { +- return this.getDisplayName(); +- } ++ @Override ++ public boolean isUnbreakable() { ++ return this.unbreakable; ++ } + +- @Override +- public void setLocalizedName(String name) { +- } ++ @Override ++ public void setUnbreakable(boolean unbreakable) { ++ this.unbreakable = unbreakable; ++ } + +- @Override +- public boolean hasLocalizedName() { +- return false; +- } ++ @Override ++ public boolean hasEnchantmentGlintOverride() { ++ return this.enchantmentGlintOverride != null; ++ } + +- @Override +- public boolean hasLore() { +- return this.lore != null && !this.lore.isEmpty(); +- } ++ @Override ++ public Boolean getEnchantmentGlintOverride() { ++ Preconditions.checkState(this.hasEnchantmentGlintOverride(), "We don't have enchantment_glint_override! Check hasEnchantmentGlintOverride first!"); ++ return this.enchantmentGlintOverride; ++ } + +- // Paper start +- @Override +- public List lore() { +- return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(this.lore) : null; +- } ++ @Override ++ public void setEnchantmentGlintOverride(Boolean override) { ++ this.enchantmentGlintOverride = override; ++ } + +- @Override +- public void lore(final List lore) { +- this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(lore) : null; +- } +- // Paper end ++ @Override ++ public boolean isFireResistant() { ++ return this.fireResistant; ++ } + +- @Override +- public boolean hasRepairCost() { +- return this.repairCost > 0; +- } ++ @Override ++ public void setFireResistant(boolean fireResistant) { ++ this.fireResistant = fireResistant; ++ } + +- @Override +- public boolean hasEnchant(Enchantment ench) { +- Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); +- return this.hasEnchants() && this.enchantments.containsKey(ench); +- } ++ @Override ++ public boolean hasMaxStackSize() { ++ return this.maxStackSize != null; ++ } + +- @Override +- public int getEnchantLevel(Enchantment ench) { +- Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); +- Integer level = this.hasEnchants() ? this.enchantments.get(ench) : null; +- if (level == null) { +- return 0; ++ @Override ++ public int getMaxStackSize() { ++ Preconditions.checkState(this.hasMaxStackSize(), "We don't have max_stack_size! Check hasMaxStackSize first!"); ++ return this.maxStackSize; + } +- return level; +- } + +- @Override +- public Map getEnchants() { +- return this.hasEnchants() ? ImmutableSortedMap.copyOfSorted(this.enchantments) : ImmutableMap.of(); // Paper +- } ++ @Override ++ public void setMaxStackSize(Integer max) { ++ Preconditions.checkArgument(max == null || max > 0, "max_stack_size must be > 0"); ++ Preconditions.checkArgument(max == null || max <= net.minecraft.world.item.Item.ABSOLUTE_MAX_STACK_SIZE, "max_stack_size must be <= 99"); ++ this.maxStackSize = max; ++ } + +- @Override +- public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { +- Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); +- if (this.enchantments == null) { +- this.enchantments = new EnchantmentMap(); // Paper ++ @Override ++ public boolean hasRarity() { ++ return this.rarity != null; + } + +- if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { +- Integer old = this.enchantments.put(ench, level); +- return old == null || old != level; ++ @Override ++ public ItemRarity getRarity() { ++ Preconditions.checkState(this.hasRarity(), "We don't have rarity! Check hasRarity first!"); ++ return this.rarity; + } +- return false; +- } + +- @Override +- public boolean removeEnchant(Enchantment ench) { +- Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); +- boolean enchantmentRemoved = this.hasEnchants() && this.enchantments.remove(ench) != null; +- // If we no longer have any enchantments, then clear enchantment tag +- if (enchantmentRemoved && this.enchantments.isEmpty()) { +- this.enchantments = null; ++ @Override ++ public void setRarity(ItemRarity rarity) { ++ this.rarity = rarity; + } +- return enchantmentRemoved; +- } + +- @Override +- public void removeEnchantments() { +- if (this.hasEnchants()) { +- this.enchantments.clear(); ++ @Override ++ public boolean hasFood() { ++ return this.food != null; + } +- } + +- @Override +- public boolean hasEnchants() { +- return !(this.enchantments == null || this.enchantments.isEmpty()); +- } ++ @Override ++ public FoodComponent getFood() { ++ return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, 0, Optional.empty(), Collections.emptyList())); ++ } + +- @Override +- public boolean hasConflictingEnchant(Enchantment ench) { +- return CraftMetaItem.checkConflictingEnchants(this.enchantments, ench); +- } ++ @Override ++ public void setFood(FoodComponent food) { ++ this.food = (food == null) ? null : new CraftFoodComponent((CraftFoodComponent) food); ++ } + +- @Override +- public void addItemFlags(ItemFlag... hideFlags) { +- for (ItemFlag f : hideFlags) { +- this.hideFlag |= this.getBitModifier(f); ++ @Override ++ public boolean hasTool() { ++ return this.tool != null; + } +- } + +- @Override +- public void removeItemFlags(ItemFlag... hideFlags) { +- for (ItemFlag f : hideFlags) { +- this.hideFlag &= ~this.getBitModifier(f); ++ @Override ++ public ToolComponent getTool() { ++ return (this.hasTool()) ? new CraftToolComponent(this.tool) : new CraftToolComponent(new Tool(Collections.emptyList(), 1.0F, 0)); + } +- } + +- @Override +- public Set getItemFlags() { +- Set currentFlags = EnumSet.noneOf(ItemFlag.class); ++ @Override ++ public void setTool(ToolComponent tool) { ++ this.tool = (tool == null) ? null : new CraftToolComponent((CraftToolComponent) tool); ++ } + +- for (ItemFlag f : ItemFlag.values()) { +- if (this.hasItemFlag(f)) { +- currentFlags.add(f); +- } ++ @Override ++ public boolean hasJukeboxPlayable() { ++ return this.jukebox != null; + } + +- return currentFlags; +- } ++ @Override ++ public JukeboxPlayableComponent getJukeboxPlayable() { ++ return (this.hasJukeboxPlayable()) ? new CraftJukeboxComponent(this.jukebox) : new CraftJukeboxComponent(new JukeboxPlayable(new EitherHolder<>(JukeboxSongs.THIRTEEN), true)); ++ } + +- @Override +- public boolean hasItemFlag(ItemFlag flag) { +- int bitModifier = this.getBitModifier(flag); +- return (this.hideFlag & bitModifier) == bitModifier; +- } ++ @Override ++ public void setJukeboxPlayable(JukeboxPlayableComponent jukeboxPlayable) { ++ this.jukebox = (jukeboxPlayable == null) ? null : new CraftJukeboxComponent((CraftJukeboxComponent) jukeboxPlayable); ++ } + +- private int getBitModifier(ItemFlag hideFlag) { +- return 1 << hideFlag.ordinal(); +- } ++ @Override ++ public boolean hasAttributeModifiers() { ++ return this.attributeModifiers != null && !this.attributeModifiers.isEmpty(); ++ } + +- @Override +- public List getLore() { +- return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromComponent)); +- } ++ @Override ++ public Multimap getAttributeModifiers() { ++ return this.hasAttributeModifiers() ? ImmutableMultimap.copyOf(this.attributeModifiers) : null; ++ } + +- // Paper start +- @Override +- public List getLoreComponents() { +- return this.lore == null ? null : new ArrayList<>(this.lore.stream().map(entry -> +- net.md_5.bungee.chat.ComponentSerializer.parse(CraftChatMessage.toJSON(entry)) +- ).collect(java.util.stream.Collectors.toList())); +- } +- // Paper end +- @Override +- public void setLore(List lore) { +- if (lore == null || lore.isEmpty()) { +- this.lore = null; +- } else { +- if (this.lore == null) { +- this.lore = new ArrayList(lore.size()); +- } else { +- this.lore.clear(); ++ private void checkAttributeList() { ++ if (this.attributeModifiers == null) { ++ this.attributeModifiers = LinkedHashMultimap.create(); + } +- CraftMetaItem.safelyAdd(lore, this.lore, false); + } +- } + +- // Paper start +- @Override +- public void setLoreComponents(List lore) { +- if (lore == null) { +- this.lore = null; +- } else { +- if (this.lore == null) { +- safelyAdd(lore, this.lore = new ArrayList<>(lore.size()), false); +- } else { +- this.lore.clear(); +- safelyAdd(lore, this.lore, false); ++ @Override ++ public Multimap getAttributeModifiers(@Nullable EquipmentSlot slot) { ++ this.checkAttributeList(); ++ SetMultimap result = LinkedHashMultimap.create(); ++ for (Map.Entry entry : this.attributeModifiers.entries()) { ++ if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { ++ result.put(entry.getKey(), entry.getValue()); ++ } + } ++ return result; + } +- } +- // Paper end +- @Override +- public boolean hasCustomModelData() { +- return this.customModelData != null; +- } +- +- @Override +- public int getCustomModelData() { +- Preconditions.checkState(this.hasCustomModelData(), "We don't have CustomModelData! Check hasCustomModelData first!"); +- return this.customModelData; +- } +- +- @Override +- public void setCustomModelData(Integer data) { +- this.customModelData = data; +- } +- +- @Override +- public boolean hasBlockData() { +- return this.blockData != null; +- } +- +- @Override +- public BlockData getBlockData(Material material) { +- BlockState defaultData = CraftBlockType.bukkitToMinecraft(material).defaultBlockState(); +- return CraftBlockData.fromData((this.hasBlockData()) ? new BlockItemStateProperties(this.blockData).apply(defaultData) : defaultData); +- } +- +- @Override +- public void setBlockData(BlockData blockData) { +- this.blockData = (blockData == null) ? null : ((CraftBlockData) blockData).toStates(); +- } +- +- @Override +- public int getRepairCost() { +- return this.repairCost; +- } +- +- @Override +- public void setRepairCost(int cost) { // TODO: Does this have limits? +- this.repairCost = cost; +- } +- +- @Override +- public boolean isHideTooltip() { +- return this.hideTooltip; +- } +- +- @Override +- public void setHideTooltip(boolean hideTooltip) { +- this.hideTooltip = hideTooltip; +- } +- +- @Override +- public boolean isUnbreakable() { +- return this.unbreakable; +- } +- +- @Override +- public void setUnbreakable(boolean unbreakable) { +- this.unbreakable = unbreakable; +- } +- +- @Override +- public boolean hasEnchantmentGlintOverride() { +- return this.enchantmentGlintOverride != null; +- } +- +- @Override +- public Boolean getEnchantmentGlintOverride() { +- Preconditions.checkState(this.hasEnchantmentGlintOverride(), "We don't have enchantment_glint_override! Check hasEnchantmentGlintOverride first!"); +- return this.enchantmentGlintOverride; +- } +- +- @Override +- public void setEnchantmentGlintOverride(Boolean override) { +- this.enchantmentGlintOverride = override; +- } + +- @Override +- public boolean isFireResistant() { +- return this.fireResistant; +- } ++ @Override ++ public Collection getAttributeModifiers(@Nonnull Attribute attribute) { ++ Preconditions.checkNotNull(attribute, "Attribute cannot be null"); ++ return this.attributeModifiers.containsKey(attribute) ? ImmutableList.copyOf(this.attributeModifiers.get(attribute)) : null; ++ } + +- @Override +- public void setFireResistant(boolean fireResistant) { +- this.fireResistant = fireResistant; +- } ++ @Override ++ public boolean addAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { ++ Preconditions.checkNotNull(attribute, "Attribute cannot be null"); ++ Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); ++ this.checkAttributeList(); ++ for (Map.Entry entry : this.attributeModifiers.entries()) { ++ Preconditions.checkArgument(!(entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine ++ } ++ return this.attributeModifiers.put(attribute, modifier); ++ } + +- @Override +- public boolean hasMaxStackSize() { +- return this.maxStackSize != null; +- } ++ @Override ++ public void setAttributeModifiers(@Nullable Multimap attributeModifiers) { ++ if (attributeModifiers == null || attributeModifiers.isEmpty()) { ++ this.attributeModifiers = LinkedHashMultimap.create(); ++ return; ++ } + +- @Override +- public int getMaxStackSize() { +- Preconditions.checkState(this.hasMaxStackSize(), "We don't have max_stack_size! Check hasMaxStackSize first!"); +- return this.maxStackSize; +- } ++ this.checkAttributeList(); ++ this.attributeModifiers.clear(); + +- @Override +- public void setMaxStackSize(Integer max) { +- Preconditions.checkArgument(max == null || max > 0, "max_stack_size must be > 0"); +- Preconditions.checkArgument(max == null || max <= net.minecraft.world.item.Item.ABSOLUTE_MAX_STACK_SIZE, "max_stack_size must be <= 99"); +- this.maxStackSize = max; +- } ++ Iterator> iterator = attributeModifiers.entries().iterator(); ++ while (iterator.hasNext()) { ++ Map.Entry next = iterator.next(); + +- @Override +- public boolean hasRarity() { +- return this.rarity != null; +- } ++ if (next.getKey() == null || next.getValue() == null) { ++ iterator.remove(); ++ continue; ++ } ++ this.attributeModifiers.put(next.getKey(), next.getValue()); ++ } ++ } + +- @Override +- public ItemRarity getRarity() { +- Preconditions.checkState(this.hasRarity(), "We don't have rarity! Check hasRarity first!"); +- return this.rarity; +- } ++ @Override ++ public boolean removeAttributeModifier(@Nonnull Attribute attribute) { ++ Preconditions.checkNotNull(attribute, "Attribute cannot be null"); ++ this.checkAttributeList(); ++ return !this.attributeModifiers.removeAll(attribute).isEmpty(); ++ } + +- @Override +- public void setRarity(ItemRarity rarity) { +- this.rarity = rarity; +- } ++ @Override ++ public boolean removeAttributeModifier(@Nullable EquipmentSlot slot) { ++ this.checkAttributeList(); ++ int removed = 0; ++ Iterator> iter = this.attributeModifiers.entries().iterator(); + +- @Override +- public boolean hasFood() { +- return this.food != null; +- } ++ while (iter.hasNext()) { ++ Map.Entry entry = iter.next(); ++ // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a - ++ // set slot are active in any slot. ++ if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { ++ iter.remove(); ++ ++removed; ++ } ++ } ++ return removed > 0; ++ } + +- @Override +- public FoodComponent getFood() { +- return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, 0, Optional.empty(), Collections.emptyList())); +- } ++ @Override ++ public boolean removeAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { ++ Preconditions.checkNotNull(attribute, "Attribute cannot be null"); ++ Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); ++ this.checkAttributeList(); ++ int removed = 0; ++ Iterator> iter = this.attributeModifiers.entries().iterator(); + +- @Override +- public void setFood(FoodComponent food) { +- this.food = (food == null) ? null : new CraftFoodComponent((CraftFoodComponent) food); +- } ++ while (iter.hasNext()) { ++ Map.Entry entry = iter.next(); ++ if (entry.getKey() == null || entry.getValue() == null) { ++ iter.remove(); ++ ++removed; ++ continue; // remove all null values while we are here ++ } + +- @Override +- public boolean hasTool() { +- return this.tool != null; +- } ++ if (entry.getKey() == attribute && entry.getValue().getKey().equals(modifier.getKey())) { ++ iter.remove(); ++ ++removed; ++ } ++ } ++ return removed > 0; ++ } + +- @Override +- public ToolComponent getTool() { +- return (this.hasTool()) ? new CraftToolComponent(this.tool) : new CraftToolComponent(new Tool(Collections.emptyList(), 1.0F, 0)); +- } ++ @Override ++ public String getAsString() { ++ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); ++ this.applyToItem(tag); ++ DataComponentPatch patch = tag.build(); ++ Tag nbt = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), patch).getOrThrow(); ++ return nbt.toString(); ++ } + +- @Override +- public void setTool(ToolComponent tool) { +- this.tool = (tool == null) ? null : new CraftToolComponent((CraftToolComponent) tool); +- } ++ @Override ++ public String getAsComponentString() { ++ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); ++ this.applyToItem(tag); ++ DataComponentPatch patch = tag.build(); + +- @Override +- public boolean hasJukeboxPlayable() { +- return this.jukebox != null; +- } ++ RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); ++ DynamicOps ops = registryAccess.createSerializationContext(NbtOps.INSTANCE); ++ Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); + +- @Override +- public JukeboxPlayableComponent getJukeboxPlayable() { +- return (this.hasJukeboxPlayable()) ? new CraftJukeboxComponent(this.jukebox) : new CraftJukeboxComponent(new JukeboxPlayable(new EitherHolder<>(JukeboxSongs.THIRTEEN), true)); +- } ++ StringJoiner componentString = new StringJoiner(",", "[", "]"); ++ for (Entry, Optional> entry : patch.entrySet()) { ++ DataComponentType componentType = entry.getKey(); ++ Optional componentValue = entry.getValue(); ++ String componentKey = componentTypeRegistry.getResourceKey(componentType).orElseThrow().location().toString(); + +- @Override +- public void setJukeboxPlayable(JukeboxPlayableComponent jukeboxPlayable) { +- this.jukebox = (jukeboxPlayable == null) ? null : new CraftJukeboxComponent((CraftJukeboxComponent) jukeboxPlayable); +- } ++ if (componentValue.isPresent()) { ++ Tag componentValueAsNBT = (Tag) ((DataComponentType) componentType).codecOrThrow().encodeStart(ops, componentValue.get()).getOrThrow(); ++ String componentValueAsNBTString = new SnbtPrinterTagVisitor("", 0, new ArrayList<>()).visit(componentValueAsNBT); ++ componentString.add(componentKey + "=" + componentValueAsNBTString); ++ } else { ++ componentString.add("!" + componentKey); ++ } ++ } + +- @Override +- public boolean hasAttributeModifiers() { +- return this.attributeModifiers != null && !this.attributeModifiers.isEmpty(); +- } ++ return componentString.toString(); ++ } + +- @Override +- public Multimap getAttributeModifiers() { +- return this.hasAttributeModifiers() ? ImmutableMultimap.copyOf(this.attributeModifiers) : null; +- } ++ @Override ++ public CustomItemTagContainer getCustomTagContainer() { ++ return new DeprecatedCustomTagContainer(this.getPersistentDataContainer()); ++ } + +- private void checkAttributeList() { +- if (this.attributeModifiers == null) { +- this.attributeModifiers = LinkedHashMultimap.create(); ++ @Override ++ public PersistentDataContainer getPersistentDataContainer() { ++ return this.persistentDataContainer; + } +- } + +- @Override +- public Multimap getAttributeModifiers(@Nullable EquipmentSlot slot) { +- this.checkAttributeList(); +- SetMultimap result = LinkedHashMultimap.create(); +- for (Map.Entry entry : this.attributeModifiers.entries()) { +- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { +- result.put(entry.getKey(), entry.getValue()); ++ private static boolean compareModifiers(Multimap first, Multimap second) { ++ if (first == null || second == null) { ++ return false; ++ } ++ for (Map.Entry entry : first.entries()) { ++ if (!second.containsEntry(entry.getKey(), entry.getValue())) { ++ return false; ++ } + } ++ for (Map.Entry entry : second.entries()) { ++ if (!first.containsEntry(entry.getKey(), entry.getValue())) { ++ return false; ++ } ++ } ++ return true; + } +- return result; +- } +- +- @Override +- public Collection getAttributeModifiers(@Nonnull Attribute attribute) { +- Preconditions.checkNotNull(attribute, "Attribute cannot be null"); +- return this.attributeModifiers.containsKey(attribute) ? ImmutableList.copyOf(this.attributeModifiers.get(attribute)) : null; +- } + +- @Override +- public boolean addAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { +- Preconditions.checkNotNull(attribute, "Attribute cannot be null"); +- Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); +- this.checkAttributeList(); +- for (Map.Entry entry : this.attributeModifiers.entries()) { +- Preconditions.checkArgument(!(entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine ++ @Override ++ public boolean hasDamage() { ++ return this.damage > 0; + } +- return this.attributeModifiers.put(attribute, modifier); +- } + +- @Override +- public void setAttributeModifiers(@Nullable Multimap attributeModifiers) { +- if (attributeModifiers == null || attributeModifiers.isEmpty()) { +- this.attributeModifiers = LinkedHashMultimap.create(); +- return; ++ @Override ++ public int getDamage() { ++ return this.damage; + } + +- this.checkAttributeList(); +- this.attributeModifiers.clear(); +- +- Iterator> iterator = attributeModifiers.entries().iterator(); +- while (iterator.hasNext()) { +- Map.Entry next = iterator.next(); ++ @Override ++ public void setDamage(int damage) { ++ this.damage = damage; ++ } + +- if (next.getKey() == null || next.getValue() == null) { +- iterator.remove(); +- continue; +- } +- this.attributeModifiers.put(next.getKey(), next.getValue()); ++ @Override ++ public boolean hasMaxDamage() { ++ return this.maxDamage != null; + } +- } + +- @Override +- public boolean removeAttributeModifier(@Nonnull Attribute attribute) { +- Preconditions.checkNotNull(attribute, "Attribute cannot be null"); +- this.checkAttributeList(); +- return !this.attributeModifiers.removeAll(attribute).isEmpty(); +- } ++ @Override ++ public int getMaxDamage() { ++ Preconditions.checkState(this.hasMaxDamage(), "We don't have max_damage! Check hasMaxDamage first!"); ++ return this.maxDamage; ++ } + +- @Override +- public boolean removeAttributeModifier(@Nullable EquipmentSlot slot) { +- this.checkAttributeList(); +- int removed = 0; +- Iterator> iter = this.attributeModifiers.entries().iterator(); ++ @Override ++ public void setMaxDamage(Integer maxDamage) { ++ this.maxDamage = maxDamage; ++ } + +- while (iter.hasNext()) { +- Map.Entry entry = iter.next(); +- // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a - +- // set slot are active in any slot. +- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { +- iter.remove(); +- ++removed; ++ @Override ++ public final boolean equals(Object object) { ++ if (object == null) { ++ return false; + } ++ if (object == this) { ++ return true; ++ } ++ if (!(object instanceof CraftMetaItem)) { ++ return false; ++ } ++ return CraftItemFactory.instance().equals(this, (ItemMeta) object); ++ } ++ ++ /** ++ * This method is almost as weird as notUncommon. ++ * Only return false if your common internals are unequal. ++ * Checking your own internals is redundant if you are not common, as notUncommon is meant for checking those 'not common' variables. ++ */ ++ @Overridden ++ boolean equalsCommon(CraftMetaItem that) { ++ return ((this.hasDisplayName() ? that.hasDisplayName() && this.displayName.equals(that.displayName) : !that.hasDisplayName())) ++ && (this.hasItemName() ? that.hasItemName() && this.itemName.equals(that.itemName) : !that.hasItemName()) ++ && (this.hasEnchants() ? that.hasEnchants() && this.enchantments.equals(that.enchantments) : !that.hasEnchants()) ++ && (Objects.equals(this.lore, that.lore)) ++ && (this.hasCustomModelData() ? that.hasCustomModelData() && this.customModelData.equals(that.customModelData) : !that.hasCustomModelData()) ++ && (this.hasBlockData() ? that.hasBlockData() && this.blockData.equals(that.blockData) : !that.hasBlockData()) ++ && (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost()) ++ && (this.hasAttributeModifiers() ? that.hasAttributeModifiers() && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : !that.hasAttributeModifiers()) ++ && (this.unhandledTags.equals(that.unhandledTags)) ++ && (this.removedTags.equals(that.removedTags)) ++ && (Objects.equals(this.customTag, that.customTag)) ++ && (this.persistentDataContainer.equals(that.persistentDataContainer)) ++ && (this.hideFlag == that.hideFlag) ++ && (this.isHideTooltip() == that.isHideTooltip()) ++ && (this.isUnbreakable() == that.isUnbreakable()) ++ && (this.hasEnchantmentGlintOverride() ? that.hasEnchantmentGlintOverride() && this.enchantmentGlintOverride.equals(that.enchantmentGlintOverride) : !that.hasEnchantmentGlintOverride()) ++ && (this.fireResistant == that.fireResistant) ++ && (this.hasMaxStackSize() ? that.hasMaxStackSize() && this.maxStackSize.equals(that.maxStackSize) : !that.hasMaxStackSize()) ++ && (this.rarity == that.rarity) ++ && (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood()) ++ && (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool()) ++ && (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable()) ++ && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) ++ && (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage()) ++ && (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper ++ && (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper ++ && (this.version == that.version); ++ } ++ ++ /** ++ * This method is a bit weird... ++ * Return true if you are a common class OR your uncommon parts are empty. ++ * Empty uncommon parts implies the NBT data would be equivalent if both were applied to an item ++ */ ++ @Overridden ++ boolean notUncommon(CraftMetaItem meta) { ++ return true; + } +- return removed > 0; +- } + +- @Override +- public boolean removeAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { +- Preconditions.checkNotNull(attribute, "Attribute cannot be null"); +- Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); +- this.checkAttributeList(); +- int removed = 0; +- Iterator> iter = this.attributeModifiers.entries().iterator(); +- +- while (iter.hasNext()) { +- Map.Entry entry = iter.next(); +- if (entry.getKey() == null || entry.getValue() == null) { +- iter.remove(); +- ++removed; +- continue; // remove all null values while we are here ++ @Override ++ public final int hashCode() { ++ return this.applyHash(); ++ } ++ ++ @Overridden ++ int applyHash() { ++ int hash = 3; ++ hash = 61 * hash + (this.hasDisplayName() ? this.displayName.hashCode() : 0); ++ hash = 61 * hash + (this.hasItemName() ? this.itemName.hashCode() : 0); ++ hash = 61 * hash + ((this.lore != null) ? this.lore.hashCode() : 0); ++ hash = 61 * hash + (this.hasCustomModelData() ? this.customModelData.hashCode() : 0); ++ hash = 61 * hash + (this.hasBlockData() ? this.blockData.hashCode() : 0); ++ hash = 61 * hash + (this.hasEnchants() ? this.enchantments.hashCode() : 0); ++ hash = 61 * hash + (this.hasRepairCost() ? this.repairCost : 0); ++ hash = 61 * hash + this.unhandledTags.hashCode(); ++ hash = 61 * hash + this.removedTags.hashCode(); ++ hash = 61 * hash + ((this.customTag != null) ? this.customTag.hashCode() : 0); ++ hash = 61 * hash + (!this.persistentDataContainer.isEmpty() ? this.persistentDataContainer.hashCode() : 0); ++ hash = 61 * hash + this.hideFlag; ++ hash = 61 * hash + (this.isHideTooltip() ? 1231 : 1237); ++ hash = 61 * hash + (this.isUnbreakable() ? 1231 : 1237); ++ hash = 61 * hash + (this.hasEnchantmentGlintOverride() ? this.enchantmentGlintOverride.hashCode() : 0); ++ hash = 61 * hash + (this.isFireResistant() ? 1231 : 1237); ++ hash = 61 * hash + (this.hasMaxStackSize() ? this.maxStackSize.hashCode() : 0); ++ hash = 61 * hash + (this.hasRarity() ? this.rarity.hashCode() : 0); ++ hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0); ++ hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0); ++ hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0); ++ hash = 61 * hash + (this.hasDamage() ? this.damage : 0); ++ hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237); ++ hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); ++ hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper ++ hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper ++ hash = 61 * hash + this.version; ++ return hash; ++ } ++ ++ @Overridden ++ @Override ++ public CraftMetaItem clone() { ++ try { ++ CraftMetaItem clone = (CraftMetaItem) super.clone(); ++ if (this.lore != null) { ++ clone.lore = new ArrayList(this.lore); ++ } ++ clone.customModelData = this.customModelData; ++ clone.blockData = this.blockData; ++ if (this.enchantments != null) { ++ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper ++ } ++ if (this.hasAttributeModifiers()) { ++ clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); ++ } ++ if (this.customTag != null) { ++ clone.customTag = this.customTag.copy(); ++ } ++ clone.removedTags = Sets.newHashSet(this.removedTags); ++ clone.persistentDataContainer = new CraftPersistentDataContainer(this.persistentDataContainer.getTagsCloned(), CraftMetaItem.DATA_TYPE_REGISTRY); // Paper - deep clone NBT tags ++ clone.hideFlag = this.hideFlag; ++ clone.hideTooltip = this.hideTooltip; ++ clone.unbreakable = this.unbreakable; ++ clone.enchantmentGlintOverride = this.enchantmentGlintOverride; ++ clone.fireResistant = this.fireResistant; ++ clone.maxStackSize = this.maxStackSize; ++ clone.rarity = this.rarity; ++ if (this.hasFood()) { ++ clone.food = new CraftFoodComponent(this.food); ++ } ++ if (this.hasTool()) { ++ clone.tool = new CraftToolComponent(this.tool); ++ } ++ if (this.hasJukeboxPlayable()) { ++ clone.jukebox = new CraftJukeboxComponent(this.jukebox); ++ } ++ clone.damage = this.damage; ++ clone.maxDamage = this.maxDamage; ++ clone.version = this.version; ++ // Paper start ++ if (this.canPlaceOnPredicates != null) { ++ clone.canPlaceOnPredicates = List.copyOf(this.canPlaceOnPredicates); ++ } ++ if (this.canBreakPredicates != null) { ++ clone.canBreakPredicates = List.copyOf(this.canBreakPredicates); ++ } ++ // Paper end ++ return clone; ++ } catch (CloneNotSupportedException e) { ++ throw new Error(e); + } ++ } + +- if (entry.getKey() == attribute && entry.getValue().getKey().equals(modifier.getKey())) { +- iter.remove(); +- ++removed; +- } ++ @Override ++ public final Map serialize() { ++ ImmutableMap.Builder map = ImmutableMap.builder(); ++ map.put(SerializableMeta.TYPE_FIELD, SerializableMeta.classMap.get(this.getClass())); ++ this.serialize(map); ++ return map.build(); + } +- return removed > 0; +- } + +- @Override +- public String getAsString() { +- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); +- this.applyToItem(tag); +- DataComponentPatch patch = tag.build(); +- Tag nbt = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), patch).getOrThrow(); +- return nbt.toString(); +- } ++ @Overridden ++ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { ++ if (this.hasDisplayName()) { ++ builder.put(CraftMetaItem.NAME.BUKKIT, CraftChatMessage.toJSON(this.displayName)); ++ } + +- @Override +- public String getAsComponentString() { +- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); +- this.applyToItem(tag); +- DataComponentPatch patch = tag.build(); +- +- RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); +- DynamicOps ops = registryAccess.createSerializationContext(NbtOps.INSTANCE); +- Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); +- +- StringJoiner componentString = new StringJoiner(",", "[", "]"); +- for (Entry, Optional> entry : patch.entrySet()) { +- DataComponentType componentType = entry.getKey(); +- Optional componentValue = entry.getValue(); +- String componentKey = componentTypeRegistry.getResourceKey(componentType).orElseThrow().location().toString(); +- +- if (componentValue.isPresent()) { +- Tag componentValueAsNBT = (Tag) ((DataComponentType) componentType).codecOrThrow().encodeStart(ops, componentValue.get()).getOrThrow(); +- String componentValueAsNBTString = new SnbtPrinterTagVisitor("", 0, new ArrayList<>()).visit(componentValueAsNBT); +- componentString.add(componentKey + "=" + componentValueAsNBTString); +- } else { +- componentString.add("!" + componentKey); ++ if (this.hasItemName()) { ++ builder.put(CraftMetaItem.ITEM_NAME.BUKKIT, CraftChatMessage.toJSON(this.itemName)); + } +- } + +- return componentString.toString(); +- } ++ if (this.hasLore()) { ++ // SPIGOT-7625: Convert lore to json before serializing it ++ List jsonLore = new ArrayList<>(); + +- @Override +- public CustomItemTagContainer getCustomTagContainer() { +- return new DeprecatedCustomTagContainer(this.getPersistentDataContainer()); +- } ++ for (Component component : this.lore) { ++ jsonLore.add(CraftChatMessage.toJSON(component)); ++ } + +- @Override +- public PersistentDataContainer getPersistentDataContainer() { +- return this.persistentDataContainer; +- } ++ builder.put(CraftMetaItem.LORE.BUKKIT, jsonLore); ++ } + +- private static boolean compareModifiers(Multimap first, Multimap second) { +- if (first == null || second == null) { +- return false; +- } +- for (Map.Entry entry : first.entries()) { +- if (!second.containsEntry(entry.getKey(), entry.getValue())) { +- return false; ++ if (this.hasCustomModelData()) { ++ builder.put(CraftMetaItem.CUSTOM_MODEL_DATA.BUKKIT, this.customModelData); + } +- } +- for (Map.Entry entry : second.entries()) { +- if (!first.containsEntry(entry.getKey(), entry.getValue())) { +- return false; ++ if (this.hasBlockData()) { ++ builder.put(CraftMetaItem.BLOCK_DATA.BUKKIT, this.blockData); + } +- } +- return true; +- } + +- @Override +- public boolean hasDamage() { +- return this.damage > 0; +- } ++ CraftMetaItem.serializeEnchantments(this.enchantments, builder, CraftMetaItem.ENCHANTMENTS); ++ CraftMetaItem.serializeModifiers(this.attributeModifiers, builder, CraftMetaItem.ATTRIBUTES); + +- @Override +- public int getDamage() { +- return this.damage; +- } ++ if (this.hasRepairCost()) { ++ builder.put(CraftMetaItem.REPAIR.BUKKIT, this.repairCost); ++ } + +- @Override +- public void setDamage(int damage) { +- this.damage = damage; +- } ++ List hideFlags = new ArrayList(); ++ for (ItemFlag hideFlagEnum : this.getItemFlags()) { ++ hideFlags.add(CraftItemFlag.bukkitToString(hideFlagEnum)); ++ } ++ if (!hideFlags.isEmpty()) { ++ builder.put(CraftMetaItem.HIDEFLAGS.BUKKIT, hideFlags); ++ } + +- @Override +- public boolean hasMaxDamage() { +- return this.maxDamage != null; +- } ++ if (this.isHideTooltip()) { ++ builder.put(CraftMetaItem.HIDE_TOOLTIP.BUKKIT, this.hideTooltip); ++ } + +- @Override +- public int getMaxDamage() { +- Preconditions.checkState(this.hasMaxDamage(), "We don't have max_damage! Check hasMaxDamage first!"); +- return this.maxDamage; +- } ++ if (this.isUnbreakable()) { ++ builder.put(CraftMetaItem.UNBREAKABLE.BUKKIT, this.unbreakable); ++ } + +- @Override +- public void setMaxDamage(Integer maxDamage) { +- this.maxDamage = maxDamage; +- } ++ if (this.hasEnchantmentGlintOverride()) { ++ builder.put(CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.BUKKIT, this.enchantmentGlintOverride); ++ } + +- @Override +- public final boolean equals(Object object) { +- if (object == null) { +- return false; +- } +- if (object == this) { +- return true; +- } +- if (!(object instanceof CraftMetaItem)) { +- return false; +- } +- return CraftItemFactory.instance().equals(this, (ItemMeta) object); +- } ++ if (this.isFireResistant()) { ++ builder.put(CraftMetaItem.FIRE_RESISTANT.BUKKIT, this.fireResistant); ++ } + +- /** +- * This method is almost as weird as notUncommon. +- * Only return false if your common internals are unequal. +- * Checking your own internals is redundant if you are not common, as notUncommon is meant for checking those 'not common' variables. +- */ +- @Overridden +- boolean equalsCommon(CraftMetaItem that) { +- return ((this.hasDisplayName() ? that.hasDisplayName() && this.displayName.equals(that.displayName) : !that.hasDisplayName())) +- && (this.hasItemName() ? that.hasItemName() && this.itemName.equals(that.itemName) : !that.hasItemName()) +- && (this.hasEnchants() ? that.hasEnchants() && this.enchantments.equals(that.enchantments) : !that.hasEnchants()) +- && (Objects.equals(this.lore, that.lore)) +- && (this.hasCustomModelData() ? that.hasCustomModelData() && this.customModelData.equals(that.customModelData) : !that.hasCustomModelData()) +- && (this.hasBlockData() ? that.hasBlockData() && this.blockData.equals(that.blockData) : !that.hasBlockData()) +- && (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost()) +- && (this.hasAttributeModifiers() ? that.hasAttributeModifiers() && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : !that.hasAttributeModifiers()) +- && (this.unhandledTags.equals(that.unhandledTags)) +- && (this.removedTags.equals(that.removedTags)) +- && (Objects.equals(this.customTag, that.customTag)) +- && (this.persistentDataContainer.equals(that.persistentDataContainer)) +- && (this.hideFlag == that.hideFlag) +- && (this.isHideTooltip() == that.isHideTooltip()) +- && (this.isUnbreakable() == that.isUnbreakable()) +- && (this.hasEnchantmentGlintOverride() ? that.hasEnchantmentGlintOverride() && this.enchantmentGlintOverride.equals(that.enchantmentGlintOverride) : !that.hasEnchantmentGlintOverride()) +- && (this.fireResistant == that.fireResistant) +- && (this.hasMaxStackSize() ? that.hasMaxStackSize() && this.maxStackSize.equals(that.maxStackSize) : !that.hasMaxStackSize()) +- && (this.rarity == that.rarity) +- && (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood()) +- && (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool()) +- && (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable()) +- && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) +- && (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage()) +- && (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper +- && (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper +- && (this.version == that.version); +- } ++ if (this.hasMaxStackSize()) { ++ builder.put(CraftMetaItem.MAX_STACK_SIZE.BUKKIT, this.maxStackSize); ++ } + +- /** +- * This method is a bit weird... +- * Return true if you are a common class OR your uncommon parts are empty. +- * Empty uncommon parts implies the NBT data would be equivalent if both were applied to an item +- */ +- @Overridden +- boolean notUncommon(CraftMetaItem meta) { +- return true; +- } ++ if (this.hasRarity()) { ++ builder.put(CraftMetaItem.RARITY.BUKKIT, this.rarity.name()); ++ } + +- @Override +- public final int hashCode() { +- return this.applyHash(); +- } ++ if (this.hasFood()) { ++ builder.put(CraftMetaItem.FOOD.BUKKIT, this.food); ++ } + +- @Overridden +- int applyHash() { +- int hash = 3; +- hash = 61 * hash + (this.hasDisplayName() ? this.displayName.hashCode() : 0); +- hash = 61 * hash + (this.hasItemName() ? this.itemName.hashCode() : 0); +- hash = 61 * hash + ((this.lore != null) ? this.lore.hashCode() : 0); +- hash = 61 * hash + (this.hasCustomModelData() ? this.customModelData.hashCode() : 0); +- hash = 61 * hash + (this.hasBlockData() ? this.blockData.hashCode() : 0); +- hash = 61 * hash + (this.hasEnchants() ? this.enchantments.hashCode() : 0); +- hash = 61 * hash + (this.hasRepairCost() ? this.repairCost : 0); +- hash = 61 * hash + this.unhandledTags.hashCode(); +- hash = 61 * hash + this.removedTags.hashCode(); +- hash = 61 * hash + ((this.customTag != null) ? this.customTag.hashCode() : 0); +- hash = 61 * hash + (!this.persistentDataContainer.isEmpty() ? this.persistentDataContainer.hashCode() : 0); +- hash = 61 * hash + this.hideFlag; +- hash = 61 * hash + (this.isHideTooltip() ? 1231 : 1237); +- hash = 61 * hash + (this.isUnbreakable() ? 1231 : 1237); +- hash = 61 * hash + (this.hasEnchantmentGlintOverride() ? this.enchantmentGlintOverride.hashCode() : 0); +- hash = 61 * hash + (this.isFireResistant() ? 1231 : 1237); +- hash = 61 * hash + (this.hasMaxStackSize() ? this.maxStackSize.hashCode() : 0); +- hash = 61 * hash + (this.hasRarity() ? this.rarity.hashCode() : 0); +- hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0); +- hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0); +- hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0); +- hash = 61 * hash + (this.hasDamage() ? this.damage : 0); +- hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237); +- hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); +- hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper +- hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper +- hash = 61 * hash + this.version; +- return hash; +- } ++ if (this.hasTool()) { ++ builder.put(CraftMetaItem.TOOL.BUKKIT, this.tool); ++ } + +- @Overridden +- @Override +- public CraftMetaItem clone() { +- try { +- CraftMetaItem clone = (CraftMetaItem) super.clone(); +- if (this.lore != null) { +- clone.lore = new ArrayList(this.lore); ++ if (this.hasJukeboxPlayable()) { ++ builder.put(CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, this.jukebox); + } +- clone.customModelData = this.customModelData; +- clone.blockData = this.blockData; +- if (this.enchantments != null) { +- clone.enchantments = new EnchantmentMap(this.enchantments); // Paper ++ ++ if (this.hasDamage()) { ++ builder.put(CraftMetaItem.DAMAGE.BUKKIT, this.damage); + } +- if (this.hasAttributeModifiers()) { +- clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); ++ ++ if (this.hasMaxDamage()) { ++ builder.put(CraftMetaItem.MAX_DAMAGE.BUKKIT, this.maxDamage); + } +- if (this.customTag != null) { +- clone.customTag = this.customTag.copy(); +- } +- clone.removedTags = Sets.newHashSet(this.removedTags); +- clone.persistentDataContainer = new CraftPersistentDataContainer(this.persistentDataContainer.getTagsCloned(), CraftMetaItem.DATA_TYPE_REGISTRY); // Paper - deep clone NBT tags +- clone.hideFlag = this.hideFlag; +- clone.hideTooltip = this.hideTooltip; +- clone.unbreakable = this.unbreakable; +- clone.enchantmentGlintOverride = this.enchantmentGlintOverride; +- clone.fireResistant = this.fireResistant; +- clone.maxStackSize = this.maxStackSize; +- clone.rarity = this.rarity; +- if (this.hasFood()) { +- clone.food = new CraftFoodComponent(this.food); ++ ++ final Map internalTags = new HashMap(); ++ this.serializeInternal(internalTags); ++ if (!internalTags.isEmpty()) { ++ CompoundTag internal = new CompoundTag(); ++ for (Map.Entry e : internalTags.entrySet()) { ++ internal.put(e.getKey(), e.getValue()); ++ } ++ try { ++ ByteArrayOutputStream buf = new ByteArrayOutputStream(); ++ NbtIo.writeCompressed(internal, buf); ++ builder.put("internal", Base64.getEncoder().encodeToString(buf.toByteArray())); ++ } catch (IOException ex) { ++ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ } + } +- if (this.hasTool()) { +- clone.tool = new CraftToolComponent(this.tool); ++ ++ // Paper start ++ final boolean canBreakAddToUnhandled = this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty(); ++ if (canBreakAddToUnhandled) { ++ this.unhandledTags.set(DataComponents.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS))); + } +- if (this.hasJukeboxPlayable()) { +- clone.jukebox = new CraftJukeboxComponent(this.jukebox); ++ final boolean canPlaceOnAddToUnhandled = this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty(); ++ if (canPlaceOnAddToUnhandled) { ++ this.unhandledTags.set(DataComponents.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON))); ++ } ++ // Paper end ++ if (!this.unhandledTags.isEmpty()) { ++ Tag unhandled = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), this.unhandledTags.build()).getOrThrow(IllegalStateException::new); ++ try { ++ ByteArrayOutputStream buf = new ByteArrayOutputStream(); ++ NbtIo.writeCompressed((CompoundTag) unhandled, buf); ++ builder.put("unhandled", Base64.getEncoder().encodeToString(buf.toByteArray())); ++ } catch (IOException ex) { ++ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ } + } +- clone.damage = this.damage; +- clone.maxDamage = this.maxDamage; +- clone.version = this.version; + // Paper start +- if (this.canPlaceOnPredicates != null) { +- clone.canPlaceOnPredicates = List.copyOf(this.canPlaceOnPredicates); ++ if (canBreakAddToUnhandled) { ++ this.unhandledTags.clear(DataComponents.CAN_BREAK); + } +- if (this.canBreakPredicates != null) { +- clone.canBreakPredicates = List.copyOf(this.canBreakPredicates); ++ if (canPlaceOnAddToUnhandled) { ++ this.unhandledTags.clear(DataComponents.CAN_PLACE_ON); + } + // Paper end +- return clone; +- } catch (CloneNotSupportedException e) { +- throw new Error(e); +- } +- } + +- @Override +- public final Map serialize() { +- ImmutableMap.Builder map = ImmutableMap.builder(); +- map.put(SerializableMeta.TYPE_FIELD, SerializableMeta.classMap.get(this.getClass())); +- this.serialize(map); +- return map.build(); +- } ++ if (!this.removedTags.isEmpty()) { ++ RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); ++ Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); + +- @Overridden +- ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { +- if (this.hasDisplayName()) { +- builder.put(CraftMetaItem.NAME.BUKKIT, CraftChatMessage.toJSON(this.displayName)); +- } ++ List removedTags = new ArrayList<>(); ++ for (DataComponentType removed : this.removedTags) { ++ String componentKey = componentTypeRegistry.getResourceKey(removed).orElseThrow().location().toString(); + +- if (this.hasItemName()) { +- builder.put(CraftMetaItem.ITEM_NAME.BUKKIT, CraftChatMessage.toJSON(this.itemName)); +- } +- +- if (this.hasLore()) { +- // SPIGOT-7625: Convert lore to json before serializing it +- List jsonLore = new ArrayList<>(); ++ removedTags.add(componentKey); ++ } + +- for (Component component : this.lore) { +- jsonLore.add(CraftChatMessage.toJSON(component)); ++ builder.put("removed", removedTags); + } + +- builder.put(CraftMetaItem.LORE.BUKKIT, jsonLore); +- } +- +- if (this.hasCustomModelData()) { +- builder.put(CraftMetaItem.CUSTOM_MODEL_DATA.BUKKIT, this.customModelData); +- } +- if (this.hasBlockData()) { +- builder.put(CraftMetaItem.BLOCK_DATA.BUKKIT, this.blockData); +- } +- +- CraftMetaItem.serializeEnchantments(this.enchantments, builder, CraftMetaItem.ENCHANTMENTS); +- CraftMetaItem.serializeModifiers(this.attributeModifiers, builder, CraftMetaItem.ATTRIBUTES); +- +- if (this.hasRepairCost()) { +- builder.put(CraftMetaItem.REPAIR.BUKKIT, this.repairCost); +- } +- +- List hideFlags = new ArrayList(); +- for (ItemFlag hideFlagEnum : this.getItemFlags()) { +- hideFlags.add(CraftItemFlag.bukkitToString(hideFlagEnum)); +- } +- if (!hideFlags.isEmpty()) { +- builder.put(CraftMetaItem.HIDEFLAGS.BUKKIT, hideFlags); +- } +- +- if (this.isHideTooltip()) { +- builder.put(CraftMetaItem.HIDE_TOOLTIP.BUKKIT, this.hideTooltip); +- } +- +- if (this.isUnbreakable()) { +- builder.put(CraftMetaItem.UNBREAKABLE.BUKKIT, this.unbreakable); +- } +- +- if (this.hasEnchantmentGlintOverride()) { +- builder.put(CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.BUKKIT, this.enchantmentGlintOverride); +- } +- +- if (this.isFireResistant()) { +- builder.put(CraftMetaItem.FIRE_RESISTANT.BUKKIT, this.fireResistant); +- } +- +- if (this.hasMaxStackSize()) { +- builder.put(CraftMetaItem.MAX_STACK_SIZE.BUKKIT, this.maxStackSize); +- } ++ if (!this.persistentDataContainer.isEmpty()) { // Store custom tags, wrapped in their compound ++ builder.put(CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, this.persistentDataContainer.serialize()); ++ } + +- if (this.hasRarity()) { +- builder.put(CraftMetaItem.RARITY.BUKKIT, this.rarity.name()); +- } ++ if (this.customTag != null) { ++ try { ++ ByteArrayOutputStream buf = new ByteArrayOutputStream(); ++ NbtIo.writeCompressed(this.customTag, buf); ++ builder.put("custom", Base64.getEncoder().encodeToString(buf.toByteArray())); ++ } catch (IOException ex) { ++ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ } ++ } + +- if (this.hasFood()) { +- builder.put(CraftMetaItem.FOOD.BUKKIT, this.food); ++ return builder; + } + +- if (this.hasTool()) { +- builder.put(CraftMetaItem.TOOL.BUKKIT, this.tool); ++ void serializeInternal(final Map unhandledTags) { + } + +- if (this.hasJukeboxPlayable()) { +- builder.put(CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, this.jukebox); +- } ++ static void serializeEnchantments(Map enchantments, ImmutableMap.Builder builder, ItemMetaKey key) { ++ if (enchantments == null || enchantments.isEmpty()) { ++ return; ++ } + +- if (this.hasDamage()) { +- builder.put(CraftMetaItem.DAMAGE.BUKKIT, this.damage); +- } ++ ImmutableMap.Builder enchants = ImmutableMap.builder(); ++ for (Map.Entry enchant : enchantments.entrySet()) { ++ enchants.put(CraftEnchantment.bukkitToString(enchant.getKey()), enchant.getValue()); ++ } + +- if (this.hasMaxDamage()) { +- builder.put(CraftMetaItem.MAX_DAMAGE.BUKKIT, this.maxDamage); ++ builder.put(key.BUKKIT, enchants.build()); + } + +- final Map internalTags = new HashMap(); +- this.serializeInternal(internalTags); +- if (!internalTags.isEmpty()) { +- CompoundTag internal = new CompoundTag(); +- for (Map.Entry e : internalTags.entrySet()) { +- internal.put(e.getKey(), e.getValue()); +- } +- try { +- ByteArrayOutputStream buf = new ByteArrayOutputStream(); +- NbtIo.writeCompressed(internal, buf); +- builder.put("internal", Base64.getEncoder().encodeToString(buf.toByteArray())); +- } catch (IOException ex) { +- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ static void serializeModifiers(Multimap modifiers, ImmutableMap.Builder builder, ItemMetaKey key) { ++ if (modifiers == null || modifiers.isEmpty()) { ++ return; + } +- } + +- // Paper start +- final boolean canBreakAddToUnhandled = this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty(); +- if (canBreakAddToUnhandled) { +- this.unhandledTags.set(DataComponents.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS))); +- } +- final boolean canPlaceOnAddToUnhandled = this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty(); +- if (canPlaceOnAddToUnhandled) { +- this.unhandledTags.set(DataComponents.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON))); +- } +- // Paper end +- if (!this.unhandledTags.isEmpty()) { +- Tag unhandled = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), this.unhandledTags.build()).getOrThrow(IllegalStateException::new); +- try { +- ByteArrayOutputStream buf = new ByteArrayOutputStream(); +- NbtIo.writeCompressed((CompoundTag) unhandled, buf); +- builder.put("unhandled", Base64.getEncoder().encodeToString(buf.toByteArray())); +- } catch (IOException ex) { +- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ Map> mods = new LinkedHashMap<>(); ++ for (Map.Entry entry : modifiers.entries()) { ++ if (entry.getKey() == null) { ++ continue; ++ } ++ Collection modCollection = modifiers.get(entry.getKey()); ++ if (modCollection == null || modCollection.isEmpty()) { ++ continue; ++ } ++ mods.put(CraftAttribute.bukkitToString(entry.getKey()), new ArrayList<>(modCollection)); + } ++ builder.put(key.BUKKIT, mods); + } +- // Paper start +- if (canBreakAddToUnhandled) { +- this.unhandledTags.clear(DataComponents.CAN_BREAK); +- } +- if (canPlaceOnAddToUnhandled) { +- this.unhandledTags.clear(DataComponents.CAN_PLACE_ON); +- } +- // Paper end +- +- if (!this.removedTags.isEmpty()) { +- RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); +- Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); +- +- List removedTags = new ArrayList<>(); +- for (DataComponentType removed : this.removedTags) { +- String componentKey = componentTypeRegistry.getResourceKey(removed).orElseThrow().location().toString(); + +- removedTags.add(componentKey); ++ static void safelyAdd(Iterable addFrom, Collection addTo, boolean possiblyJsonInput) { ++ if (addFrom == null) { ++ return; + } + +- builder.put("removed", removedTags); +- } ++ for (Object object : addFrom) { ++ // Paper start - support components ++ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[] baseComponentArr) { ++ addTo.add(CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(baseComponentArr))); ++ } else ++ // Paper end ++ if (!(object instanceof String)) { ++ if (object != null) { ++ // SPIGOT-7399: Null check via if is important, ++ // otherwise object.getClass().getName() could throw an error for a valid argument -> when it is null which is valid, ++ // when using Preconditions ++ throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); ++ } + +- if (!this.persistentDataContainer.isEmpty()) { // Store custom tags, wrapped in their compound +- builder.put(CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, this.persistentDataContainer.serialize()); +- } ++ addTo.add(Component.empty()); ++ } else { ++ String entry = object.toString(); ++ Component component = (possiblyJsonInput) ? CraftChatMessage.fromJSONOrString(entry) : CraftChatMessage.fromStringOrNull(entry); + +- if (this.customTag != null) { +- try { +- ByteArrayOutputStream buf = new ByteArrayOutputStream(); +- NbtIo.writeCompressed(this.customTag, buf); +- builder.put("custom", Base64.getEncoder().encodeToString(buf.toByteArray())); +- } catch (IOException ex) { +- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); ++ if (component != null) { ++ addTo.add(component); ++ } else { ++ addTo.add(Component.empty()); ++ } ++ } + } + } + +- return builder; +- } +- +- void serializeInternal(final Map unhandledTags) { +- } +- +- static void serializeEnchantments(Map enchantments, ImmutableMap.Builder builder, ItemMetaKey key) { +- if (enchantments == null || enchantments.isEmpty()) { +- return; +- } +- +- ImmutableMap.Builder enchants = ImmutableMap.builder(); +- for (Map.Entry enchant : enchantments.entrySet()) { +- enchants.put(CraftEnchantment.bukkitToString(enchant.getKey()), enchant.getValue()); +- } +- +- builder.put(key.BUKKIT, enchants.build()); +- } +- +- static void serializeModifiers(Multimap modifiers, ImmutableMap.Builder builder, ItemMetaKey key) { +- if (modifiers == null || modifiers.isEmpty()) { +- return; +- } +- +- Map> mods = new LinkedHashMap<>(); +- for (Map.Entry entry : modifiers.entries()) { +- if (entry.getKey() == null) { +- continue; +- } +- Collection modCollection = modifiers.get(entry.getKey()); +- if (modCollection == null || modCollection.isEmpty()) { +- continue; ++ static boolean checkConflictingEnchants(Map enchantments, Enchantment ench) { ++ if (enchantments == null || enchantments.isEmpty()) { ++ return false; + } +- mods.put(CraftAttribute.bukkitToString(entry.getKey()), new ArrayList<>(modCollection)); +- } +- builder.put(key.BUKKIT, mods); +- } + +- static void safelyAdd(Iterable addFrom, Collection addTo, boolean possiblyJsonInput) { +- if (addFrom == null) { +- return; +- } +- +- for (Object object : addFrom) { +- // Paper start - support components +- if(object instanceof net.md_5.bungee.api.chat.BaseComponent[] baseComponentArr) { +- addTo.add(CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(baseComponentArr))); +- } else +- // Paper end +- if (!(object instanceof String)) { +- if (object != null) { +- // SPIGOT-7399: Null check via if is important, +- // otherwise object.getClass().getName() could throw an error for a valid argument -> when it is null which is valid, +- // when using Preconditions +- throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); +- } +- +- addTo.add(Component.empty()); +- } else { +- String entry = object.toString(); +- Component component = (possiblyJsonInput) ? CraftChatMessage.fromJSONOrString(entry) : CraftChatMessage.fromStringOrNull(entry); +- +- if (component != null) { +- addTo.add(component); +- } else { +- addTo.add(Component.empty()); ++ for (Enchantment enchant : enchantments.keySet()) { ++ if (enchant.conflictsWith(ench)) { ++ return true; + } + } +- } +- } + +- static boolean checkConflictingEnchants(Map enchantments, Enchantment ench) { +- if (enchantments == null || enchantments.isEmpty()) { + return false; + } + +- for (Enchantment enchant : enchantments.keySet()) { +- if (enchant.conflictsWith(ench)) { +- return true; +- } +- } +- +- return false; +- } +- +- @Override +- public final String toString() { +- return SerializableMeta.classMap.get(this.getClass()) + "_META:" + this.serialize(); // TODO: cry +- } +- +- public int getVersion() { +- return this.version; +- } +- +- @Override +- public void setVersion(int version) { +- this.version = version; +- } +- - public static Set getHandledTags() { - synchronized (CraftMetaItem.HANDLED_TAGS) { - if (CraftMetaItem.HANDLED_TAGS.isEmpty()) { @@ -533,7 +3358,6 @@ index 044713d5b2661405200590914f73b07e73aeb48f..58da8cb19a8444c634cbc1f39e93503c - CraftMetaFirework.FIREWORKS.TYPE, - CraftMetaEnchantedBook.STORED_ENCHANTMENTS.TYPE, - CraftMetaCharge.EXPLOSION.TYPE, -- CraftMetaBlockState.BLOCK_ENTITY_TAG.TYPE, - CraftMetaKnowledgeBook.BOOK_RECIPES.TYPE, - CraftMetaTropicalFishBucket.ENTITY_TAG.TYPE, - CraftMetaTropicalFishBucket.BUCKET_ENTITY_TAG.TYPE, @@ -548,72 +3372,86 @@ index 044713d5b2661405200590914f73b07e73aeb48f..58da8cb19a8444c634cbc1f39e93503c - )); - } - return CraftMetaItem.HANDLED_TAGS; -+ // Paper start - improve checking handled tags -+ @org.jetbrains.annotations.VisibleForTesting -+ public static final Map, Set>> HANDLED_DCTS_PER_TYPE = new HashMap<>(); -+ private static final Set> DEFAULT_HANDLED_DCTS = Set.of( -+ CraftMetaItem.NAME.TYPE, -+ CraftMetaItem.ITEM_NAME.TYPE, -+ CraftMetaItem.LORE.TYPE, -+ CraftMetaItem.CUSTOM_MODEL_DATA.TYPE, -+ CraftMetaItem.BLOCK_DATA.TYPE, -+ CraftMetaItem.REPAIR.TYPE, -+ CraftMetaItem.ENCHANTMENTS.TYPE, -+ CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP.TYPE, -+ CraftMetaItem.HIDE_TOOLTIP.TYPE, -+ CraftMetaItem.UNBREAKABLE.TYPE, -+ CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.TYPE, -+ CraftMetaItem.FIRE_RESISTANT.TYPE, -+ CraftMetaItem.MAX_STACK_SIZE.TYPE, -+ CraftMetaItem.RARITY.TYPE, -+ CraftMetaItem.FOOD.TYPE, -+ CraftMetaItem.TOOL.TYPE, -+ CraftMetaItem.JUKEBOX_PLAYABLE.TYPE, -+ CraftMetaItem.DAMAGE.TYPE, -+ CraftMetaItem.MAX_DAMAGE.TYPE, -+ CraftMetaItem.CUSTOM_DATA.TYPE, -+ CraftMetaItem.ATTRIBUTES.TYPE, -+ CraftMetaItem.CAN_PLACE_ON.TYPE, // Paper -+ CraftMetaItem.CAN_BREAK.TYPE // Paper -+ ); -+ public static Set> getTopLevelHandledDcts(final Class clazz) { -+ synchronized (HANDLED_DCTS_PER_TYPE) { -+ if (HANDLED_DCTS_PER_TYPE.isEmpty()) { -+ final Map, Set>> map = new HashMap<>(); -+ map.put(CraftMetaArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE)); -+ map.put(CraftMetaArmorStand.class, Set.of(CraftMetaArmorStand.ENTITY_TAG.TYPE)); -+ map.put(CraftMetaAxolotlBucket.class, Set.of(CraftMetaAxolotlBucket.ENTITY_TAG.TYPE, CraftMetaAxolotlBucket.BUCKET_ENTITY_TAG.TYPE)); -+ map.put(CraftMetaBanner.class, Set.of(/*CraftMetaBlockState.BLOCK_ENTITY_TAG.NBT, */CraftMetaBanner.PATTERNS.TYPE)); // banner uses same tag as block state -+ map.put(CraftMetaBlockState.class, Set.of(CraftMetaBlockState.BLOCK_ENTITY_TAG.TYPE)); -+ map.put(CraftMetaBook.class, Set.of(CraftMetaBook.BOOK_CONTENT.TYPE)); -+ map.put(CraftMetaBookSigned.class, Set.of(CraftMetaBookSigned.BOOK_CONTENT.TYPE)); -+ map.put(CraftMetaBundle.class, Set.of(CraftMetaBundle.ITEMS.TYPE)); -+ map.put(CraftMetaCharge.class, Set.of(CraftMetaCharge.EXPLOSION.TYPE)); -+ map.put(CraftMetaColorableArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE, CraftMetaLeatherArmor.COLOR.TYPE)); -+ map.put(CraftMetaCompass.class, Set.of(CraftMetaCompass.LODESTONE_TARGET.TYPE)); -+ map.put(CraftMetaCrossbow.class, Set.of(CraftMetaCrossbow.CHARGED_PROJECTILES.TYPE)); -+ map.put(CraftMetaEnchantedBook.class, Set.of(CraftMetaEnchantedBook.STORED_ENCHANTMENTS.TYPE)); -+ map.put(CraftMetaEntityTag.class, Set.of(CraftMetaEntityTag.ENTITY_TAG.TYPE)); -+ map.put(CraftMetaFirework.class, Set.of(CraftMetaFirework.FIREWORKS.TYPE)); -+ map.put(CraftMetaKnowledgeBook.class, Set.of(CraftMetaKnowledgeBook.BOOK_RECIPES.TYPE)); -+ map.put(CraftMetaLeatherArmor.class, Set.of(CraftMetaLeatherArmor.COLOR.TYPE)); -+ map.put(CraftMetaMap.class, Set.of(CraftMetaMap.MAP_COLOR.TYPE, CraftMetaMap.MAP_POST_PROCESSING.TYPE, CraftMetaMap.MAP_ID.TYPE)); -+ map.put(CraftMetaMusicInstrument.class, Set.of(CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT.TYPE)); -+ map.put(CraftMetaOminousBottle.class, Set.of(CraftMetaOminousBottle.OMINOUS_BOTTLE_AMPLIFIER.TYPE)); -+ map.put(CraftMetaPotion.class, Set.of(CraftMetaPotion.POTION_CONTENTS.TYPE)); -+ map.put(CraftMetaSkull.class, Set.of(CraftMetaSkull.SKULL_PROFILE.TYPE, CraftMetaSkull.NOTE_BLOCK_SOUND.TYPE)); -+ map.put(CraftMetaSpawnEgg.class, Set.of(CraftMetaSpawnEgg.ENTITY_TAG.TYPE)); -+ map.put(CraftMetaSuspiciousStew.class, Set.of(CraftMetaSuspiciousStew.EFFECTS.TYPE)); -+ map.put(CraftMetaTropicalFishBucket.class, Set.of(CraftMetaTropicalFishBucket.ENTITY_TAG.TYPE, CraftMetaTropicalFishBucket.BUCKET_ENTITY_TAG.TYPE)); -+ -+ for (final Map.Entry, Set>> entry : map.entrySet()) { -+ final ArrayList> topLevelTags = new ArrayList<>(entry.getValue()); -+ // add tags common to CraftMetaItem to all -+ topLevelTags.addAll(DEFAULT_HANDLED_DCTS); -+ HANDLED_DCTS_PER_TYPE.put(entry.getKey(), Set.copyOf(topLevelTags)); -+ } -+ } -+ return HANDLED_DCTS_PER_TYPE.getOrDefault(clazz, DEFAULT_HANDLED_DCTS); ++ @Override ++ public final String toString() { ++ return SerializableMeta.classMap.get(this.getClass()) + "_META:" + this.serialize(); // TODO: cry ++ } ++ ++ public int getVersion() { ++ return this.version; ++ } ++ ++ @Override ++ public void setVersion(int version) { ++ this.version = version; ++ } ++ ++ // Paper start - improve checking handled tags ++ @org.jetbrains.annotations.VisibleForTesting ++ public static final Map, Set>> HANDLED_DCTS_PER_TYPE = new HashMap<>(); ++ private static final Set> DEFAULT_HANDLED_DCTS = Set.of( ++ CraftMetaItem.NAME.TYPE, ++ CraftMetaItem.ITEM_NAME.TYPE, ++ CraftMetaItem.LORE.TYPE, ++ CraftMetaItem.CUSTOM_MODEL_DATA.TYPE, ++ CraftMetaItem.BLOCK_DATA.TYPE, ++ CraftMetaItem.REPAIR.TYPE, ++ CraftMetaItem.ENCHANTMENTS.TYPE, ++ CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP.TYPE, ++ CraftMetaItem.HIDE_TOOLTIP.TYPE, ++ CraftMetaItem.UNBREAKABLE.TYPE, ++ CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.TYPE, ++ CraftMetaItem.FIRE_RESISTANT.TYPE, ++ CraftMetaItem.MAX_STACK_SIZE.TYPE, ++ CraftMetaItem.RARITY.TYPE, ++ CraftMetaItem.FOOD.TYPE, ++ CraftMetaItem.TOOL.TYPE, ++ CraftMetaItem.JUKEBOX_PLAYABLE.TYPE, ++ CraftMetaItem.DAMAGE.TYPE, ++ CraftMetaItem.MAX_DAMAGE.TYPE, ++ CraftMetaItem.CUSTOM_DATA.TYPE, ++ CraftMetaItem.ATTRIBUTES.TYPE, ++ CraftMetaItem.CAN_PLACE_ON.TYPE, // Paper ++ CraftMetaItem.CAN_BREAK.TYPE // Paper ++ ); ++ public static Set> getTopLevelHandledDcts(final Class clazz) { ++ synchronized (HANDLED_DCTS_PER_TYPE) { ++ if (HANDLED_DCTS_PER_TYPE.isEmpty()) { ++ final Map, Set>> map = new HashMap<>(); ++ map.put(CraftMetaArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE)); ++ map.put(CraftMetaArmorStand.class, Set.of(CraftMetaArmorStand.ENTITY_TAG.TYPE)); ++ map.put(CraftMetaAxolotlBucket.class, Set.of(CraftMetaAxolotlBucket.ENTITY_TAG.TYPE, CraftMetaAxolotlBucket.BUCKET_ENTITY_TAG.TYPE)); ++ map.put(CraftMetaBanner.class, Set.of(/*CraftMetaBlockState.BLOCK_ENTITY_TAG.NBT, */CraftMetaBanner.PATTERNS.TYPE)); // banner uses same tag as block state ++ map.put(CraftMetaBlockState.class, Set.of(CraftMetaBlockState.BLOCK_ENTITY_TAG.TYPE)); ++ map.put(CraftMetaBook.class, Set.of(CraftMetaBook.BOOK_CONTENT.TYPE)); ++ map.put(CraftMetaBookSigned.class, Set.of(CraftMetaBookSigned.BOOK_CONTENT.TYPE)); ++ map.put(CraftMetaBundle.class, Set.of(CraftMetaBundle.ITEMS.TYPE)); ++ map.put(CraftMetaCharge.class, Set.of(CraftMetaCharge.EXPLOSION.TYPE)); ++ map.put(CraftMetaColorableArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE, CraftMetaLeatherArmor.COLOR.TYPE)); ++ map.put(CraftMetaCompass.class, Set.of(CraftMetaCompass.LODESTONE_TARGET.TYPE)); ++ map.put(CraftMetaCrossbow.class, Set.of(CraftMetaCrossbow.CHARGED_PROJECTILES.TYPE)); ++ map.put(CraftMetaEnchantedBook.class, Set.of(CraftMetaEnchantedBook.STORED_ENCHANTMENTS.TYPE)); ++ map.put(CraftMetaEntityTag.class, Set.of(CraftMetaEntityTag.ENTITY_TAG.TYPE)); ++ map.put(CraftMetaFirework.class, Set.of(CraftMetaFirework.FIREWORKS.TYPE)); ++ map.put(CraftMetaKnowledgeBook.class, Set.of(CraftMetaKnowledgeBook.BOOK_RECIPES.TYPE)); ++ map.put(CraftMetaLeatherArmor.class, Set.of(CraftMetaLeatherArmor.COLOR.TYPE)); ++ map.put(CraftMetaMap.class, Set.of(CraftMetaMap.MAP_COLOR.TYPE, CraftMetaMap.MAP_POST_PROCESSING.TYPE, CraftMetaMap.MAP_ID.TYPE)); ++ map.put(CraftMetaMusicInstrument.class, Set.of(CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT.TYPE)); ++ map.put(CraftMetaOminousBottle.class, Set.of(CraftMetaOminousBottle.OMINOUS_BOTTLE_AMPLIFIER.TYPE)); ++ map.put(CraftMetaPotion.class, Set.of(CraftMetaPotion.POTION_CONTENTS.TYPE)); ++ map.put(CraftMetaSkull.class, Set.of(CraftMetaSkull.SKULL_PROFILE.TYPE, CraftMetaSkull.NOTE_BLOCK_SOUND.TYPE)); ++ map.put(CraftMetaSpawnEgg.class, Set.of(CraftMetaSpawnEgg.ENTITY_TAG.TYPE)); ++ map.put(CraftMetaSuspiciousStew.class, Set.of(CraftMetaSuspiciousStew.EFFECTS.TYPE)); ++ map.put(CraftMetaTropicalFishBucket.class, Set.of(CraftMetaTropicalFishBucket.ENTITY_TAG.TYPE, CraftMetaTropicalFishBucket.BUCKET_ENTITY_TAG.TYPE)); ++ ++ for (final Map.Entry, Set>> entry : map.entrySet()) { ++ final ArrayList> topLevelTags = new ArrayList<>(entry.getValue()); ++ // add tags common to CraftMetaItem to all ++ topLevelTags.addAll(DEFAULT_HANDLED_DCTS); ++ HANDLED_DCTS_PER_TYPE.put(entry.getKey(), Set.copyOf(topLevelTags)); ++ } ++ } ++ return HANDLED_DCTS_PER_TYPE.getOrDefault(clazz, DEFAULT_HANDLED_DCTS); } } + // Paper end - improve checking handled data component types diff --git a/patches/server/0970-General-ItemMeta-fixes.patch b/patches/server/0970-General-ItemMeta-fixes.patch index 1f0a2364a753..92d50c3f17e7 100644 --- a/patches/server/0970-General-ItemMeta-fixes.patch +++ b/patches/server/0970-General-ItemMeta-fixes.patch @@ -445,7 +445,7 @@ index d7e5491cc0296563fb9fdf28d64b21a10c08ea4a..224ea52574b80bb087c5c62eaf1d4626 private static Material shieldToBannerHack() { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java -index a395c7ce952f4a60a5edf80e8731afa6388d18ea..e213ac74f8f4a62b7b8b2b7889250f5cdeb348fe 100644 +index e064af399dcae40b4f35aa993d356b1462f91d6c..27a275f324891e395bf3fd3038c0b9a724bbbf66 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java @@ -34,7 +34,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta, WritableBo @@ -458,20 +458,9 @@ index a395c7ce952f4a60a5edf80e8731afa6388d18ea..e213ac74f8f4a62b7b8b2b7889250f5c // We store the pages in their raw original text representation. See SPIGOT-5063, SPIGOT-5350, SPIGOT-3206 diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -index 3f78a0935d738854182254b345064e3c225dcd5f..218df87c596d47b431dbbf2aa42822ef174f948f 100644 +index 806c1cbee7c4e23eee38c8f400ec2d924c9a360c..bf7293835dbb4e9c55a51655ca5d85bc87c63d1d 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -@@ -116,8 +116,8 @@ public class CraftMetaBookSigned extends CraftMetaItem implements BookMeta { - } - } - -- this.resolved = SerializableMeta.getObject(Boolean.class, map, CraftMetaBookSigned.RESOLVED.BUKKIT, true); -- this.generation = SerializableMeta.getObject(Integer.class, map, CraftMetaBookSigned.GENERATION.BUKKIT, true); -+ this.resolved = SerializableMeta.getBoolean(map, CraftMetaBookSigned.RESOLVED.BUKKIT); // Paper - General ItemMeta fixes -+ this.generation = SerializableMeta.getObjectOptionally(Integer.class, map, CraftMetaBookSigned.GENERATION.BUKKIT, true).orElse(0); // Paper - General ItemMeta Fixes - } - - @Override @@ -129,7 +129,7 @@ public class CraftMetaBookSigned extends CraftMetaItem implements BookMeta { for (Component page : this.pages) { list.add(Filterable.passThrough(page)); @@ -481,21 +470,6 @@ index 3f78a0935d738854182254b345064e3c225dcd5f..218df87c596d47b431dbbf2aa42822ef } } -@@ -358,7 +358,13 @@ public class CraftMetaBookSigned extends CraftMetaItem implements BookMeta { - } - - if (this.pages != null) { -- builder.put(CraftMetaBookSigned.BOOK_PAGES.BUKKIT, ImmutableList.copyOf(this.pages)); -+ // Paper start - deserialization expects json -+ final List jsonPages = new ArrayList<>(this.pages.size()); -+ for (final Component page : this.pages) { -+ jsonPages.add(CraftChatMessage.toJSON(page)); -+ } -+ builder.put(CraftMetaBookSigned.BOOK_PAGES.BUKKIT, ImmutableList.copyOf(jsonPages)); -+ // Paper end - deserialization expects json - } - - if (this.resolved) { diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java index 2736a87a6c481da0575e6e29ea08faa539c24378..51da0db4da3549efd69f367e28450408968fa8d0 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java @@ -671,7 +645,7 @@ index 3f6c5cbbf63631e4b72dc43558651ea94f31ca78..da474a5b963d8e6769d120e9091e60ed return true; } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java -index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed67c3e8e38 100644 +index 9600b23666668d7d581e2920a4e03e59cc2339fb..0eceacbb096481d3bd31f5f99e964c88aea2e3fb 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java @@ -54,7 +54,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { @@ -740,23 +714,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6 effects.add((FireworkEffect) obj); } } -@@ -185,9 +189,13 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { - } - - List effects = new ArrayList<>(); -- for (FireworkEffect effect : this.effects) { -- effects.add(CraftMetaFirework.getExplosion(effect)); -+ // Paper start - fix NPE with effects list being null -+ if (this.effects != null) { -+ for (FireworkEffect effect : this.effects) { -+ effects.add(CraftMetaFirework.getExplosion(effect)); -+ } - } -+ // Paper end - - itemTag.put(CraftMetaFirework.FIREWORKS, new Fireworks(this.power, effects)); - } -@@ -212,7 +220,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { +@@ -214,7 +218,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { } boolean isFireworkEmpty() { @@ -765,7 +723,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6 } boolean hasPower() { -@@ -228,7 +236,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { +@@ -230,7 +234,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { if (meta instanceof CraftMetaFirework that) { return (this.hasPower() ? that.hasPower() && this.power == that.power : !that.hasPower()) @@ -774,7 +732,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6 } return true; -@@ -246,7 +254,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { +@@ -248,7 +252,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { if (this.hasPower()) { hash = 61 * hash + this.power; } @@ -783,7 +741,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6 hash = 61 * hash + 13 * this.effects.hashCode(); } return hash != original ? CraftMetaFirework.class.hashCode() ^ hash : hash; -@@ -256,7 +264,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { +@@ -258,7 +262,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { Builder serialize(Builder builder) { super.serialize(builder); @@ -792,7 +750,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6 builder.put(CraftMetaFirework.EXPLOSIONS.BUKKIT, ImmutableList.copyOf(this.effects)); } -@@ -281,6 +289,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { +@@ -283,6 +287,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { @Override public void addEffect(FireworkEffect effect) { Preconditions.checkArgument(effect != null, "FireworkEffect cannot be null"); @@ -800,7 +758,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6 if (this.effects == null) { this.effects = new ArrayList(); } -@@ -290,6 +299,10 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { +@@ -292,6 +297,10 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { @Override public void addEffects(FireworkEffect... effects) { Preconditions.checkArgument(effects != null, "effects cannot be null"); @@ -811,7 +769,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6 if (effects.length == 0) { return; } -@@ -308,7 +321,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { +@@ -310,7 +319,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { @Override public void addEffects(Iterable effects) { Preconditions.checkArgument(effects != null, "effects cannot be null"); @@ -820,7 +778,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6 } @Override -@@ -343,7 +356,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { +@@ -345,7 +354,7 @@ class CraftMetaFirework extends CraftMetaItem implements FireworkMeta { @Override public void setPower(int power) { Preconditions.checkArgument(power >= 0, "power cannot be less than zero: %s", power); @@ -830,7 +788,7 @@ index 97b7085250d749c5e46352b372068b51de89bc7f..7277e7ee566aabf6e01937072d949ed6 } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 58da8cb19a8444c634cbc1f39e93503ca8e2ecab..776f4dcc0b61a5b8ee4020a283cfcfacefbe682e 100644 +index 11c6c8d9c14fb31d1819a5c61e3b743b0b6c6d65..a82b8e123d3df343f643bdcf007bc3632518c6a1 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -182,9 +182,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { @@ -877,307 +835,306 @@ index 58da8cb19a8444c634cbc1f39e93503ca8e2ecab..776f4dcc0b61a5b8ee4020a283cfcfac this.displayName = component; }); @@ -802,7 +808,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - Map mods = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); - Multimap result = LinkedHashMultimap.create(); - if (mods == null) { -- return result; -+ return null; // Paper - null is different from an empty map - } + Map mods = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); + Multimap result = LinkedHashMultimap.create(); + if (mods == null) { +- return result; ++ return null; // Paper - null is different from an empty map + } - for (Object obj : mods.keySet()) { -@@ -905,7 +911,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - itemTag.put(CraftMetaItem.JUKEBOX_PLAYABLE, this.jukebox.getHandle()); - } + for (Object obj : mods.keySet()) { +@@ -909,7 +915,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + itemTag.put(CraftMetaItem.DAMAGE, this.damage); + } -- if (this.hasDamage()) { -+ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage - itemTag.put(CraftMetaItem.DAMAGE, this.damage); - } +- if (this.hasMaxDamage()) { ++ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage + itemTag.put(CraftMetaItem.MAX_DAMAGE, this.maxDamage); + } @@ -970,10 +976,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - - void applyModifiers(Multimap modifiers, CraftMetaItem.Applicator tag) { -- if (modifiers == null || modifiers.isEmpty()) { -- if (this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES)) { -- tag.put(CraftMetaItem.ATTRIBUTES, new ItemAttributeModifiers(Collections.emptyList(), false)); -- } -+ if (modifiers == null/* || modifiers.isEmpty()*/) { // Paper - empty modifiers has a specific meaning, they should still be saved -+ // Paper - don't save ItemFlag if the underlying data isn't present - return; } + void applyModifiers(Multimap modifiers, CraftMetaItem.Applicator tag) { +- if (modifiers == null || modifiers.isEmpty()) { +- if (this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES)) { +- tag.put(CraftMetaItem.ATTRIBUTES, new ItemAttributeModifiers(Collections.emptyList(), false)); +- } ++ if (modifiers == null/* || modifiers.isEmpty()*/) { // Paper - empty modifiers has a specific meaning, they should still be saved ++ // Paper - don't save ItemFlag if the underlying data isn't present + return; + } + @@ -1010,7 +1014,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Overridden - boolean isEmpty() { -- return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper -+ return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasJukeboxPlayable() || this.hasDamageValue() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper - } + @Overridden + boolean isEmpty() { +- return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper ++ return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasJukeboxPlayable() || this.hasDamageValue() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper + } - // Paper start + // Paper start @@ -1106,6 +1110,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public void lore(final List lore) { -+ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines - this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(lore) : null; - } - // Paper end + @Override + public void lore(final List lore) { ++ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines + this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(lore) : null; + } + // Paper end @@ -1164,7 +1169,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public void removeEnchantments() { - if (this.hasEnchants()) { -- this.enchantments.clear(); -+ this.enchantments = null; // Paper - Correctly clear enchantments + @Override + public void removeEnchantments() { + if (this.hasEnchants()) { +- this.enchantments.clear(); ++ this.enchantments = null; // Paper - Correctly clear enchantments + } } - } @@ -1230,6 +1235,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - // Paper end - @Override - public void setLore(List lore) { -+ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines - if (lore == null || lore.isEmpty()) { - this.lore = null; - } else { + // Paper end + @Override + public void setLore(List lore) { ++ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines + if (lore == null || lore.isEmpty()) { + this.lore = null; + } else { @@ -1245,6 +1251,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - // Paper start - @Override - public void setLoreComponents(List lore) { -+ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines - if (lore == null) { - this.lore = null; - } else { + // Paper start + @Override + public void setLoreComponents(List lore) { ++ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines + if (lore == null) { + this.lore = null; + } else { @@ -1386,7 +1393,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public FoodComponent getFood() { -- return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, 0, Optional.empty(), Collections.emptyList())); -+ return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, FoodProperties.DEFAULT_EAT_SECONDS, Optional.empty(), Collections.emptyList())); // Paper - create a valid food properties - } + @Override + public FoodComponent getFood() { +- return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, 0, Optional.empty(), Collections.emptyList())); ++ return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, FoodProperties.DEFAULT_EAT_SECONDS, Optional.empty(), Collections.emptyList())); // Paper - create a valid food properties + } - @Override + @Override @@ -1442,7 +1449,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public Multimap getAttributeModifiers(@Nullable EquipmentSlot slot) { -- this.checkAttributeList(); -+ if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components - SetMultimap result = LinkedHashMultimap.create(); - for (Map.Entry entry : this.attributeModifiers.entries()) { - if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + @Override + public Multimap getAttributeModifiers(@Nullable EquipmentSlot slot) { +- this.checkAttributeList(); ++ if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components + SetMultimap result = LinkedHashMultimap.create(); + for (Map.Entry entry : this.attributeModifiers.entries()) { + if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { @@ -1455,6 +1462,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public Collection getAttributeModifiers(@Nonnull Attribute attribute) { - Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -+ if (this.attributeModifiers == null) return null; // Paper - fix NPE - return this.attributeModifiers.containsKey(attribute) ? ImmutableList.copyOf(this.attributeModifiers.get(attribute)) : null; - } + @Override + public Collection getAttributeModifiers(@Nonnull Attribute attribute) { + Preconditions.checkNotNull(attribute, "Attribute cannot be null"); ++ if (this.attributeModifiers == null) return null; // Paper - fix NPE + return this.attributeModifiers.containsKey(attribute) ? ImmutableList.copyOf(this.attributeModifiers.get(attribute)) : null; + } @@ -1462,10 +1470,12 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - public boolean addAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { - Preconditions.checkNotNull(attribute, "Attribute cannot be null"); - Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); -- this.checkAttributeList(); -+ if (this.attributeModifiers != null) { // Paper - for (Map.Entry entry : this.attributeModifiers.entries()) { - Preconditions.checkArgument(!(entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine + public boolean addAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { + Preconditions.checkNotNull(attribute, "Attribute cannot be null"); + Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); +- this.checkAttributeList(); ++ if (this.attributeModifiers != null) { // Paper + for (Map.Entry entry : this.attributeModifiers.entries()) { + Preconditions.checkArgument(!(entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine + } ++ } // Paper ++ this.checkAttributeList(); // Paper - moved down + return this.attributeModifiers.put(attribute, modifier); } -+ } // Paper -+ this.checkAttributeList(); // Paper - moved down - return this.attributeModifiers.put(attribute, modifier); - } @@ -1476,8 +1486,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return; - } + return; + } -- this.checkAttributeList(); -- this.attributeModifiers.clear(); -+ // Paper start - fix modifiers meta -+ if (this.attributeModifiers != null) { -+ this.attributeModifiers.clear(); -+ } -+ // Paper end +- this.checkAttributeList(); +- this.attributeModifiers.clear(); ++ // Paper start - fix modifiers meta ++ if (this.attributeModifiers != null) { ++ this.attributeModifiers.clear(); ++ } ++ // Paper end - Iterator> iterator = attributeModifiers.entries().iterator(); - while (iterator.hasNext()) { + Iterator> iterator = attributeModifiers.entries().iterator(); + while (iterator.hasNext()) { @@ -1487,6 +1500,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - iterator.remove(); - continue; + iterator.remove(); + continue; + } ++ this.checkAttributeList(); // Paper - moved down + this.attributeModifiers.put(next.getKey(), next.getValue()); } -+ this.checkAttributeList(); // Paper - moved down - this.attributeModifiers.put(next.getKey(), next.getValue()); } - } @@ -1494,13 +1508,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public boolean removeAttributeModifier(@Nonnull Attribute attribute) { - Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -- this.checkAttributeList(); -+ if (this.attributeModifiers == null) return false; // Paper - return !this.attributeModifiers.removeAll(attribute).isEmpty(); - } + @Override + public boolean removeAttributeModifier(@Nonnull Attribute attribute) { + Preconditions.checkNotNull(attribute, "Attribute cannot be null"); +- this.checkAttributeList(); ++ if (this.attributeModifiers == null) return false; // Paper + return !this.attributeModifiers.removeAll(attribute).isEmpty(); + } - @Override - public boolean removeAttributeModifier(@Nullable EquipmentSlot slot) { -- this.checkAttributeList(); -+ if (this.attributeModifiers == null) return false; // Paper - int removed = 0; - Iterator> iter = this.attributeModifiers.entries().iterator(); + @Override + public boolean removeAttributeModifier(@Nullable EquipmentSlot slot) { +- this.checkAttributeList(); ++ if (this.attributeModifiers == null) return false; // Paper + int removed = 0; + Iterator> iter = this.attributeModifiers.entries().iterator(); @@ -1520,7 +1534,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - public boolean removeAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { - Preconditions.checkNotNull(attribute, "Attribute cannot be null"); - Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); -- this.checkAttributeList(); -+ if (this.attributeModifiers == null) return false; // Paper - int removed = 0; - Iterator> iter = this.attributeModifiers.entries().iterator(); + public boolean removeAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { + Preconditions.checkNotNull(attribute, "Attribute cannot be null"); + Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); +- this.checkAttributeList(); ++ if (this.attributeModifiers == null) return false; // Paper + int removed = 0; + Iterator> iter = this.attributeModifiers.entries().iterator(); @@ -1542,7 +1556,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public String getAsString() { -- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); -+ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator() {}; // Paper - support updating profile after resolving it - this.applyToItem(tag); - DataComponentPatch patch = tag.build(); - Tag nbt = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), patch).getOrThrow(); + @Override + public String getAsString() { +- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); ++ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator() {}; // Paper - support updating profile after resolving it + this.applyToItem(tag); + DataComponentPatch patch = tag.build(); + Tag nbt = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), patch).getOrThrow(); @@ -1551,7 +1565,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public String getAsComponentString() { -- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); -+ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator() {}; // Paper - this.applyToItem(tag); - DataComponentPatch patch = tag.build(); + @Override + public String getAsComponentString() { +- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); ++ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator() {}; // Paper - support updating profile after resolving it + this.applyToItem(tag); + DataComponentPatch patch = tag.build(); @@ -1591,6 +1605,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (first == null || second == null) { - return false; - } -+ if (first.isEmpty() && second.isEmpty()) return true; // Paper - empty modifiers are equivalent - for (Map.Entry entry : first.entries()) { - if (!second.containsEntry(entry.getKey(), entry.getValue())) { + if (first == null || second == null) { return false; + } ++ if (first.isEmpty() && second.isEmpty()) return true; // Paper - empty modifiers are equivalent + for (Map.Entry entry : first.entries()) { + if (!second.containsEntry(entry.getKey(), entry.getValue())) { + return false; @@ -1606,19 +1621,33 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public boolean hasDamage() { -- return this.damage > 0; -+ return this.damage != null && this.damage > 0; // Paper - null check - } + @Override + public boolean hasDamage() { +- return this.damage > 0; ++ return this.damage != null && this.damage > 0; // Paper - null check + } - @Override - public int getDamage() { -- return this.damage; -+ return this.damage == null ? 0 : this.damage; // Paper - null check - } + @Override + public int getDamage() { +- return this.damage; ++ return this.damage == null ? 0 : this.damage; // Paper - null check + } - @Override - public void setDamage(int damage) { -+ Preconditions.checkArgument(damage >= 0, "Damage cannot be negative"); // Paper -+ Preconditions.checkArgument(!this.hasMaxDamage() || damage <= this.maxDamage, "Damage cannot exceed max damage"); // Paper - this.damage = damage; - } + @Override + public void setDamage(int damage) { ++ Preconditions.checkArgument(damage >= 0, "Damage cannot be negative"); // Paper ++ Preconditions.checkArgument(!this.hasMaxDamage() || damage <= this.maxDamage, "Damage cannot exceed max damage"); // Paper + this.damage = damage; + } -+ // Paper start - preserve empty/0 damage -+ @Override -+ public boolean hasDamageValue() { -+ return this.damage != null; -+ } ++ // Paper start - preserve empty/0 damage ++ @Override ++ public boolean hasDamageValue() { ++ return this.damage != null; ++ } + -+ @Override -+ public void resetDamage() { -+ this.damage = null; -+ } -+ // Paper end - preserve empty/0 damage ++ @Override ++ public void resetDamage() { ++ this.damage = null; ++ } ++ // Paper end - preserve empty/0 damage + - @Override - public boolean hasMaxDamage() { - return this.maxDamage != null; + @Override + public boolean hasMaxDamage() { + return this.maxDamage != null; @@ -1632,6 +1661,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public void setMaxDamage(Integer maxDamage) { -+ Preconditions.checkArgument(maxDamage == null || maxDamage > 0, "Max damage should be positive"); // Paper - this.maxDamage = maxDamage; - } + @Override + public void setMaxDamage(Integer maxDamage) { ++ Preconditions.checkArgument(maxDamage == null || maxDamage > 0, "Max damage should be positive"); // Paper + this.maxDamage = maxDamage; + } @@ -1663,7 +1693,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - && (this.hasCustomModelData() ? that.hasCustomModelData() && this.customModelData.equals(that.customModelData) : !that.hasCustomModelData()) - && (this.hasBlockData() ? that.hasBlockData() && this.blockData.equals(that.blockData) : !that.hasBlockData()) - && (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost()) -- && (this.hasAttributeModifiers() ? that.hasAttributeModifiers() && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : !that.hasAttributeModifiers()) + && (this.hasCustomModelData() ? that.hasCustomModelData() && this.customModelData.equals(that.customModelData) : !that.hasCustomModelData()) + && (this.hasBlockData() ? that.hasBlockData() && this.blockData.equals(that.blockData) : !that.hasBlockData()) + && (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost()) +- && (this.hasAttributeModifiers() ? that.hasAttributeModifiers() && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : !that.hasAttributeModifiers()) + && (this.attributeModifiers != null ? that.attributeModifiers != null && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : that.attributeModifiers == null) // Paper - track only null modifiers - && (this.unhandledTags.equals(that.unhandledTags)) - && (this.removedTags.equals(that.removedTags)) - && (Objects.equals(this.customTag, that.customTag)) + && (this.unhandledTags.equals(that.unhandledTags)) + && (this.removedTags.equals(that.removedTags)) + && (Objects.equals(this.customTag, that.customTag)) @@ -1678,7 +1708,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - && (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood()) - && (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool()) - && (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable()) -- && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) -+ && (Objects.equals(this.damage, that.damage)) // Paper - preserve empty/0 damage - && (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage()) - && (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper - && (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper + && (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood()) + && (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool()) + && (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable()) +- && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) ++ && (Objects.equals(this.damage, that.damage)) // Paper - preserve empty/0 damage + && (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage()) + && (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper + && (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper @@ -1724,9 +1754,9 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0); - hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0); - hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0); -- hash = 61 * hash + (this.hasDamage() ? this.damage : 0); -- hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237); -- hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); -+ hash = 61 * hash + (this.hasDamageValue() ? this.damage : -1); // Paper - preserve empty/0 damage -+ hash = 61 * hash + (this.hasMaxDamage() ? this.maxDamage.hashCode() : 0); // Paper - max damage is not a boolean -+ hash = 61 * hash + (this.attributeModifiers != null ? this.attributeModifiers.hashCode() : 0); // Paper - track only null attributes - hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper - hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper - hash = 61 * hash + this.version; + hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0); + hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0); + hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0); +- hash = 61 * hash + (this.hasDamage() ? this.damage : 0); +- hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237); +- hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); ++ hash = 61 * hash + (this.hasDamageValue() ? this.damage : -1); // Paper - preserve empty/0 damage ++ hash = 61 * hash + (this.hasMaxDamage() ? this.maxDamage.hashCode() : 0); // Paper - max damage is not a boolean ++ hash = 61 * hash + (this.attributeModifiers != null ? this.attributeModifiers.hashCode() : 0); // Paper - track only null attributes + hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper + hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper + hash = 61 * hash + this.version; @@ -1746,7 +1776,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (this.enchantments != null) { - clone.enchantments = new EnchantmentMap(this.enchantments); // Paper - } -- if (this.hasAttributeModifiers()) { -+ if (this.attributeModifiers != null) { // Paper - clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); - } - if (this.customTag != null) { + if (this.enchantments != null) { + clone.enchantments = new EnchantmentMap(this.enchantments); // Paper + } +- if (this.hasAttributeModifiers()) { ++ if (this.attributeModifiers != null) { // Paper + clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); + } + if (this.customTag != null) { @@ -1874,7 +1904,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - builder.put(CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, this.jukebox); - } + builder.put(CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, this.jukebox); + } -- if (this.hasDamage()) { -+ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage - builder.put(CraftMetaItem.DAMAGE.BUKKIT, this.damage); - } +- if (this.hasDamage()) { ++ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage + builder.put(CraftMetaItem.DAMAGE.BUKKIT, this.damage); + } @@ -1975,7 +2005,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } - - static void serializeModifiers(Multimap modifiers, ImmutableMap.Builder builder, ItemMetaKey key) { -- if (modifiers == null || modifiers.isEmpty()) { -+ if (modifiers == null/* || modifiers.isEmpty()*/) { // Paper - null and an empty map have different behaviors - return; } + static void serializeModifiers(Multimap modifiers, ImmutableMap.Builder builder, ItemMetaKey key) { +- if (modifiers == null || modifiers.isEmpty()) { ++ if (modifiers == null/* || modifiers.isEmpty()*/) { // Paper - null and an empty map have different behaviors + return; + } + @@ -2057,7 +2087,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - // Paper start - improve checking handled tags - @org.jetbrains.annotations.VisibleForTesting - public static final Map, Set>> HANDLED_DCTS_PER_TYPE = new HashMap<>(); -- private static final Set> DEFAULT_HANDLED_DCTS = Set.of( -+ protected static final Set> DEFAULT_HANDLED_DCTS = Set.of( - CraftMetaItem.NAME.TYPE, - CraftMetaItem.ITEM_NAME.TYPE, - CraftMetaItem.LORE.TYPE, -@@ -2125,7 +2155,12 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - // Paper end - improve checking handled data component types + // Paper start - improve checking handled tags + @org.jetbrains.annotations.VisibleForTesting + public static final Map, Set>> HANDLED_DCTS_PER_TYPE = new HashMap<>(); +- private static final Set> DEFAULT_HANDLED_DCTS = Set.of( ++ protected static final Set> DEFAULT_HANDLED_DCTS = Set.of( + CraftMetaItem.NAME.TYPE, + CraftMetaItem.ITEM_NAME.TYPE, + CraftMetaItem.LORE.TYPE, +@@ -2126,6 +2156,12 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { protected static Optional getOrEmpty(DataComponentPatch tag, ItemMetaKeyType type) { -- Optional result = tag.get(type.TYPE); + Optional result = tag.get(type.TYPE); + // Paper start + return getOrEmpty(tag, type.TYPE); + } @@ -1473,10 +1430,10 @@ index 17705059b81942e4df43a4a5180092e09c985ade..80e6b85a107d5236edba99540cb5074e } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/SerializableMeta.java b/src/main/java/org/bukkit/craftbukkit/inventory/SerializableMeta.java -index 8b407a33b04af6ae396ada0b8aca7dc246d314ef..d204845cf0b9de00589593469755cb8e42e0aa67 100644 +index b7e93a6ec72ec3e3390fefa52fda0c2cd8e17c0c..758778650bebf7b96eefab42543e812849124b2f 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/SerializableMeta.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/SerializableMeta.java -@@ -123,4 +123,21 @@ public final class SerializableMeta implements ConfigurationSerializable { +@@ -128,4 +128,21 @@ public final class SerializableMeta implements ConfigurationSerializable { } throw new IllegalArgumentException(field + "(" + object + ") is not a valid " + clazz); } diff --git a/patches/server/0977-Fix-equipment-slot-and-group-API.patch b/patches/server/0977-Fix-equipment-slot-and-group-API.patch index 12c1d026ea6f..5c9b90b127fb 100644 --- a/patches/server/0977-Fix-equipment-slot-and-group-API.patch +++ b/patches/server/0977-Fix-equipment-slot-and-group-API.patch @@ -52,29 +52,29 @@ index 9d74577af071954e1e37201a96368c1360076209..eafa54c870c3e2aef30c3f9f96f51660 throw new IllegalArgumentException("Not implemented. This is a bug"); } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 776f4dcc0b61a5b8ee4020a283cfcfacefbe682e..9aef0223cd790d9f4a74dfe22e7926027c08dca5 100644 +index a82b8e123d3df343f643bdcf007bc3632518c6a1..cc9de0a940deb21c1ed660567e7d419fedcfd376 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -1452,7 +1452,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components - SetMultimap result = LinkedHashMultimap.create(); - for (Map.Entry entry : this.attributeModifiers.entries()) { -- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components + SetMultimap result = LinkedHashMultimap.create(); + for (Map.Entry entry : this.attributeModifiers.entries()) { +- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group - result.put(entry.getKey(), entry.getValue()); + result.put(entry.getKey(), entry.getValue()); + } } - } @@ -1520,9 +1520,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - while (iter.hasNext()) { - Map.Entry entry = iter.next(); -- // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a - -- // set slot are active in any slot. -- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + while (iter.hasNext()) { + Map.Entry entry = iter.next(); +- // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a - +- // set slot are active in any slot. +- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group - iter.remove(); - ++removed; - } + iter.remove(); + ++removed; + } diff --git a/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java b/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ee0bfe4edb134d7ea3a3b97f5102a7f3122c3b99 diff --git a/patches/server/0979-Prevent-sending-oversized-item-data-in-equipment-and.patch b/patches/server/0979-Prevent-sending-oversized-item-data-in-equipment-and.patch index 9e1dfe1f309b..5ba0aae52edd 100644 --- a/patches/server/0979-Prevent-sending-oversized-item-data-in-equipment-and.patch +++ b/patches/server/0979-Prevent-sending-oversized-item-data-in-equipment-and.patch @@ -214,10 +214,10 @@ index 60c65af218d533d53b765ba2175fed163c32c126..a0f5839719ca0ce6ed048229f074041b } } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 66707853328b6b23771c88abd0cf5a7ef766bb71..7a6c8a64bd119fd1f2fc245f84cbb332ecd937e3 100644 +index de2b1f8e1c9883babe4ded372d51de616d9b44ca..9a0d4120d4735c2d8057bc55d2599bc38d5b4714 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3322,7 +3322,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3351,7 +3351,7 @@ public abstract class LivingEntity extends Entity implements Attackable { } }); diff --git a/patches/server/0989-Configurable-damage-tick-when-blocking-with-shield.patch b/patches/server/0989-Configurable-damage-tick-when-blocking-with-shield.patch index 8c0e7e79e6c9..c309af0ddb75 100644 --- a/patches/server/0989-Configurable-damage-tick-when-blocking-with-shield.patch +++ b/patches/server/0989-Configurable-damage-tick-when-blocking-with-shield.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable damage tick when blocking with shield diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 7a6c8a64bd119fd1f2fc245f84cbb332ecd937e3..45e5f14c3ad7cf25e11baa1554eb5fabac41ebe2 100644 +index 9a0d4120d4735c2d8057bc55d2599bc38d5b4714..2812269f11169a9e5c7ce5c3e86a2ead0268c7c9 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2380,7 +2380,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2409,7 +2409,7 @@ public abstract class LivingEntity extends Entity implements Attackable { CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, originalDamage, f, true); // Paper - fix taken/dealt param order } diff --git a/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch b/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch index 1fa4249c11bc..6dd4a1a9b2f2 100644 --- a/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch +++ b/patches/server/0991-Chunk-System-Starlight-from-Moonrise.patch @@ -26377,7 +26377,7 @@ index 4d7e234d379a451c4bb53bc2fcdf22cb191f8d1a..cf33e22ae85cd30b4f5d526dbfececca return crashreportsystemdetails; } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index 3cbb59df34156479d24a8251f2b3acbb5e60dc2c..6b9354e3ac064daa3101e71d8e54e883f628f70c 100644 +index 09e60ea5c25f23bcc7e24f16c7a31f616d249ff9..478d6e2eaa1a8fded571ff2c2c623028c3def94d 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -199,7 +199,7 @@ import org.bukkit.event.player.PlayerToggleSneakEvent; @@ -29678,10 +29678,10 @@ index 8f88ccec6b8947ca2738dc07c23aebe258145c83..cdc704364cf339084537d089e654f607 // Paper start - implement pointers diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 33541edc8bb2d673342448046fa29767f171bbf3..1bc343df0e7b8e6e3fadc970a4a4c8d787d93828 100644 +index 3480f06d4476c5c200246e6200e2eda2a5de1a5a..62bfde27a182be24710eb3b72448e82da58afc8f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -3491,12 +3491,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3492,12 +3492,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public int getViewDistance() { @@ -29698,7 +29698,7 @@ index 33541edc8bb2d673342448046fa29767f171bbf3..1bc343df0e7b8e6e3fadc970a4a4c8d7 } @Override -@@ -3506,7 +3508,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3507,7 +3509,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setSimulationDistance(final int simulationDistance) { @@ -29709,7 +29709,7 @@ index 33541edc8bb2d673342448046fa29767f171bbf3..1bc343df0e7b8e6e3fadc970a4a4c8d7 } @Override -@@ -3516,6 +3520,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3517,6 +3521,8 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public void setSendViewDistance(final int viewDistance) { diff --git a/patches/server/0992-Rewrite-dataconverter-system.patch b/patches/server/0992-Rewrite-dataconverter-system.patch index b03980be16bf..ea19e60350c3 100644 --- a/patches/server/0992-Rewrite-dataconverter-system.patch +++ b/patches/server/0992-Rewrite-dataconverter-system.patch @@ -29388,10 +29388,10 @@ index 1d287dd7379e56f7fd4b425880b850cd843f5789..8ab7ca373a885fbe658013c9c6a2e38d return nbttagcompound; }); diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index be56e7a7607d3119e560f38e800ad4bbfe1e7714..5a04134973dd1db7f778a57ec5f185feec370990 100644 +index fa60f4e05e3303a7fe4faab0098c1fb439a24354..ca1c0955be0d0f78972f39c4bd4afffd46c2fb45 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -522,7 +522,7 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -516,7 +516,7 @@ public final class CraftMagicNumbers implements UnsafeValues { net.minecraft.nbt.CompoundTag compound = deserializeNbtFromBytes(data); final int dataVersion = compound.getInt("DataVersion"); @@ -29400,7 +29400,7 @@ index be56e7a7607d3119e560f38e800ad4bbfe1e7714..5a04134973dd1db7f778a57ec5f185fe return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.parse(MinecraftServer.getServer().registryAccess(), compound).orElseThrow()); } -@@ -543,7 +543,7 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -537,7 +537,7 @@ public final class CraftMagicNumbers implements UnsafeValues { net.minecraft.nbt.CompoundTag compound = deserializeNbtFromBytes(data); int dataVersion = compound.getInt("DataVersion"); diff --git a/patches/server/0995-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch b/patches/server/0995-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch index 198e443db026..cb921d96da21 100644 --- a/patches/server/0995-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch +++ b/patches/server/0995-Improve-Maps-in-item-frames-performance-and-bug-fixe.patch @@ -25,10 +25,10 @@ index db30381b3aeab83bcd0d1a341e4056d7c36a6f11..fc011c30628d77d55defe421db6ac194 } } diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java -index e27fd3a1eb1a128613e328910f09f290007f48d5..54ba25632c2a9e1c93a5b3a0b92e5280864c49d6 100644 +index d0b51d96d6795b5fa03bc195b90324680545b752..09bcbc0ae36e4e69fee87a7e0c49acf496117a39 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java +++ b/src/main/java/net/minecraft/world/entity/player/Player.java -@@ -807,6 +807,14 @@ public abstract class Player extends LivingEntity { +@@ -808,6 +808,14 @@ public abstract class Player extends LivingEntity { return null; } // CraftBukkit end diff --git a/patches/server/0996-Strip-raytracing-for-EntityLiving-hasLineOfSight.patch b/patches/server/0996-Strip-raytracing-for-EntityLiving-hasLineOfSight.patch index 46a4939bd436..101484351a01 100644 --- a/patches/server/0996-Strip-raytracing-for-EntityLiving-hasLineOfSight.patch +++ b/patches/server/0996-Strip-raytracing-for-EntityLiving-hasLineOfSight.patch @@ -26,10 +26,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 45e5f14c3ad7cf25e11baa1554eb5fabac41ebe2..25a7dfddb44a11f6e20c459141a61270c0c12d4c 100644 +index 2812269f11169a9e5c7ce5c3e86a2ead0268c7c9..f53e6ac5ac1ac0ca0d9095c812a2e60a165d36dd 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3743,7 +3743,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3772,7 +3772,7 @@ public abstract class LivingEntity extends Entity implements Attackable { Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists diff --git a/patches/server/1009-Optimize-Hoppers.patch b/patches/server/1009-Optimize-Hoppers.patch index 500c718a871e..3eaae2401748 100644 --- a/patches/server/1009-Optimize-Hoppers.patch +++ b/patches/server/1009-Optimize-Hoppers.patch @@ -105,7 +105,7 @@ index cd3b952a228c09077c2e74183a34ddb32811280b..c0563260277f9f4bd9ff08993b2efb4b } diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f3eb1c74d 100644 +index 0d6132abd49d66fbf84c046e09144cb33651be15..b3cd4bf8e4d7718e8d98ef5e085621ecc85d93a9 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java @@ -156,6 +156,43 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen @@ -370,7 +370,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f private static boolean ejectItems(Level world, BlockPos pos, HopperBlockEntity blockEntity) { Container iinventory = HopperBlockEntity.getAttachedContainer(world, pos, blockEntity); -@@ -209,47 +443,50 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -209,48 +443,51 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen if (HopperBlockEntity.isFullContainer(iinventory, enumdirection)) { return false; } else { @@ -380,6 +380,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f - if (!itemstack.isEmpty()) { - int j = itemstack.getCount(); - // CraftBukkit start - Call event when pushing items into other inventories +- ItemStack original = itemstack.copy(); - CraftItemStack oitemstack = CraftItemStack.asCraftMirror(blockEntity.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot - - Inventory destinationInventory; @@ -395,7 +396,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f - InventoryMoveItemEvent event = new InventoryMoveItemEvent(blockEntity.getOwner().getInventory(), oitemstack, destinationInventory, true); - world.getCraftServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { -- blockEntity.setItem(i, itemstack); +- blockEntity.setItem(i, original); - blockEntity.setCooldown(world.spigotConfig.hopperTransfer); // Delay hopper checks // Spigot - return false; - } @@ -423,6 +424,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f + // if (!itemstack.isEmpty()) { + // int j = itemstack.getCount(); + // // CraftBukkit start - Call event when pushing items into other inventories ++ // ItemStack original = itemstack.copy(); + // CraftItemStack oitemstack = CraftItemStack.asCraftMirror(blockEntity.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot + + // Inventory destinationInventory; @@ -452,7 +454,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f + + // itemstack.setCount(j); + // if (j == 1) { -+ // blockEntity.setItem(i, itemstack); ++ // blockEntity.setItem(i, original); + // } + // } + //} @@ -462,7 +464,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f } } } -@@ -300,7 +537,6 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -301,7 +538,6 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen return false; } } @@ -470,7 +472,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f return true; } -@@ -311,6 +547,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -312,6 +548,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen if (iinventory != null) { Direction enumdirection = Direction.DOWN; @@ -478,12 +480,13 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f int[] aint = HopperBlockEntity.getSlots(iinventory, enumdirection); int i = aint.length; -@@ -346,44 +583,47 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -347,45 +584,48 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen ItemStack itemstack = iinventory.getItem(i); if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(ihopper, iinventory, itemstack, i, enumdirection)) { - int j = itemstack.getCount(); - // CraftBukkit start - Call event on collection of items from inventories into the hopper +- ItemStack original = itemstack.copy(); - CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot - - Inventory sourceInventory; @@ -500,7 +503,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f - - Bukkit.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { -- iinventory.setItem(i, itemstack); +- iinventory.setItem(i, original); - - if (ihopper instanceof HopperBlockEntity) { - ((HopperBlockEntity) ihopper).setCooldown(world.spigotConfig.hopperTransfer); // Spigot @@ -524,6 +527,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f + return hopperPull(world, ihopper, iinventory, itemstack, i); + // int j = itemstack.getCount(); + // // CraftBukkit start - Call event on collection of items from inventories into the hopper ++ // ItemStack original = itemstack.copy(); + // CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot + + // Inventory sourceInventory; @@ -558,13 +562,13 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f + + // itemstack.setCount(j); + // if (j == 1) { -+ // iinventory.setItem(i, itemstack); ++ // iinventory.setItem(i, original); + // } + // Paper end - Perf: Optimize Hoppers } return false; -@@ -392,12 +632,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -394,12 +634,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen public static boolean addItem(Container inventory, ItemEntity itemEntity) { boolean flag = false; // CraftBukkit start @@ -580,7 +584,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f ItemStack itemstack = itemEntity.getItem().copy(); ItemStack itemstack1 = HopperBlockEntity.addItem((Container) null, inventory, itemstack, (Direction) null); -@@ -491,7 +733,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -493,7 +735,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen stack = stack.split(to.getMaxStackSize()); } // Spigot end @@ -590,7 +594,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f stack = leftover; // Paper - Make hoppers respect inventory max stack size flag = true; } else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) { -@@ -571,14 +815,20 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -573,14 +817,20 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen @Nullable public static Container getContainerAt(Level world, BlockPos pos) { @@ -613,7 +617,7 @@ index 92086ca118d55ec49cefa5bf18977f8706e3e4b4..8310d132006043e93c612890514c4c7f iinventory = HopperBlockEntity.getEntityContainer(world, x, y, z); } -@@ -613,13 +863,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen +@@ -615,13 +865,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen @Nullable private static Container getEntityContainer(Level world, double x, double y, double z) { diff --git a/patches/server/1018-API-for-checking-sent-chunks.patch b/patches/server/1018-API-for-checking-sent-chunks.patch index 54f091fb695b..137772f48751 100644 --- a/patches/server/1018-API-for-checking-sent-chunks.patch +++ b/patches/server/1018-API-for-checking-sent-chunks.patch @@ -20,10 +20,10 @@ index 82e8ce73b77accd6a4210f88c9fccb325ae367d4..91c4219b2abf1b5be3dc35f7b8403884 } } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 1bc343df0e7b8e6e3fadc970a4a4c8d787d93828..7eea190ce8a62960ecc42ff56a4ef71b754184fb 100644 +index 62bfde27a182be24710eb3b72448e82da58afc8f..d01b45a48d412e3cb591acee101730704574448a 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -3483,6 +3483,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -3484,6 +3484,35 @@ public class CraftPlayer extends CraftHumanEntity implements Player { } // Paper end diff --git a/patches/server/1019-Improve-boat-collision-performance.patch b/patches/server/1019-Improve-boat-collision-performance.patch index f646d2f8e9d0..4be9644f8768 100644 --- a/patches/server/1019-Improve-boat-collision-performance.patch +++ b/patches/server/1019-Improve-boat-collision-performance.patch @@ -17,10 +17,10 @@ index 42d7ecfab6f72517904451d9df3f0404b176fdb2..5869f2f5c72f736e6b077683327c64b9 }; diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 25a7dfddb44a11f6e20c459141a61270c0c12d4c..affc39430e1f77e09768d2f614fcd5073d5a9270 100644 +index f53e6ac5ac1ac0ca0d9095c812a2e60a165d36dd..b9d107a86bbb9ace55fec9477f052ae3c1bd4e35 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -1436,7 +1436,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1437,7 +1437,7 @@ public abstract class LivingEntity extends Entity implements Attackable { if (!source.is(DamageTypeTags.IS_PROJECTILE)) { Entity entity = source.getDirectEntity(); @@ -29,7 +29,7 @@ index 25a7dfddb44a11f6e20c459141a61270c0c12d4c..affc39430e1f77e09768d2f614fcd507 LivingEntity entityliving = (LivingEntity) entity; this.blockUsingShield(entityliving); -@@ -1533,8 +1533,13 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1544,8 +1544,13 @@ public abstract class LivingEntity extends Entity implements Attackable { double d0 = 0.0D; double d1 = 0.0D; Entity entity2 = source.getDirectEntity(); @@ -45,7 +45,7 @@ index 25a7dfddb44a11f6e20c459141a61270c0c12d4c..affc39430e1f77e09768d2f614fcd507 Projectile iprojectile = (Projectile) entity2; DoubleDoubleImmutablePair doubledoubleimmutablepair = iprojectile.calculateHorizontalHurtKnockbackDirection(this, source); -@@ -2325,7 +2330,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2349,7 +2354,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING)); Entity entity = damagesource.getDirectEntity(); diff --git a/patches/server/1023-Properly-resend-entities.patch b/patches/server/1023-Properly-resend-entities.patch index 398462967a35..7b7e3cc85fdd 100644 --- a/patches/server/1023-Properly-resend-entities.patch +++ b/patches/server/1023-Properly-resend-entities.patch @@ -102,7 +102,7 @@ index a8debfad8c8e66099f8a9aedc6f1971a8576dade..7796e191747be545e744564a2b0b6579 } diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 14fb62dedabf2d858bea1877c2e28d1a7b6f5be4..bad83045ff9409678a0699cdc0781efd8ef30a44 100644 +index 1aa8b914e79c0d48094cc22df60ee9750ec3ccd6..369b3485f452ac157b3ebf88b4f1970605d302d2 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java @@ -393,7 +393,7 @@ public abstract class PlayerList { @@ -166,10 +166,10 @@ index f1fb4e830c6720d09b22056e3d0b9a08fe2bd472..83f3ffdd8fa901b3de580d2359cdb5ea public boolean equals(Object object) { return object instanceof Entity ? ((Entity) object).id == this.id : false; diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index affc39430e1f77e09768d2f614fcd5073d5a9270..b9cef93fe382b666bec04ca95eeaf2d8acbb3c40 100644 +index b9d107a86bbb9ace55fec9477f052ae3c1bd4e35..542dff99accb726e70bf2a245925991c5509e0d8 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3845,6 +3845,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3874,6 +3874,11 @@ public abstract class LivingEntity extends Entity implements Attackable { return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; } diff --git a/patches/server/1025-Registry-Modification-API.patch b/patches/server/1025-Registry-Modification-API.patch index c45b11903807..dc555c750dfd 100644 --- a/patches/server/1025-Registry-Modification-API.patch +++ b/patches/server/1025-Registry-Modification-API.patch @@ -1347,10 +1347,10 @@ index d21b7e39d71c785f47f790e1ad4be33a8e8e6e51..a47421425a8d5d2f07e08890fded0f7b + // Paper end - RegistrySet API } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 5a04134973dd1db7f778a57ec5f185feec370990..8dba6c4a2e1f305cf576e8bfdca5d0c07ab871ae 100644 +index ca1c0955be0d0f78972f39c4bd4afffd46c2fb45..0984843ff443ba40406839d06f83304902ee4f43 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -685,6 +685,21 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -679,6 +679,21 @@ public final class CraftMagicNumbers implements UnsafeValues { } // Paper end - lifecycle event API diff --git a/patches/server/1028-Proxy-ItemStack-to-CraftItemStack.patch b/patches/server/1028-Proxy-ItemStack-to-CraftItemStack.patch index aba1d9b341aa..ad3c75feb2c2 100644 --- a/patches/server/1028-Proxy-ItemStack-to-CraftItemStack.patch +++ b/patches/server/1028-Proxy-ItemStack-to-CraftItemStack.patch @@ -160,7 +160,7 @@ index be36336a3c7d1ae88277f4ee1be70075001de7a7..814e8ece6821e359b504e8c4d140cc38 @Override diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java -index 9d2feff3df87cfeefe7105d954854af05cef6f69..07539ebfefa3352de5ee7a17f2724cf2c979f399 100644 +index d03f4a767f6c7fe7d6bcef20e6676c39d9657584..bae3dd5fc67e6b3d98a5e63ffbf639c5042f8843 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java @@ -100,13 +100,14 @@ public class CraftItemType implements ItemType.Typed, Han @@ -205,10 +205,10 @@ index 9c004e7cb46841d874ab997bf2e3b63ae763aec7..d7c8f26b21276d9ff1d5c7c9738cc112 + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 8dba6c4a2e1f305cf576e8bfdca5d0c07ab871ae..d70c5546c8bd6f364fad9b24880b6867efdab644 100644 +index 0984843ff443ba40406839d06f83304902ee4f43..3137391cadef7c67019561e65fedd0664e689eae 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -700,6 +700,13 @@ public final class CraftMagicNumbers implements UnsafeValues { +@@ -694,6 +694,13 @@ public final class CraftMagicNumbers implements UnsafeValues { } // Paper end - hack to get tags for non server-backed registries diff --git a/patches/server/1029-Prioritize-Minecraft-commands-in-function-parsing.patch b/patches/server/1030-Prioritize-Minecraft-commands-in-function-parsing-an.patch similarity index 100% rename from patches/server/1029-Prioritize-Minecraft-commands-in-function-parsing.patch rename to patches/server/1030-Prioritize-Minecraft-commands-in-function-parsing-an.patch diff --git a/patches/server/1030-optimize-dirt-and-snow-spreading.patch b/patches/server/1031-optimize-dirt-and-snow-spreading.patch similarity index 100% rename from patches/server/1030-optimize-dirt-and-snow-spreading.patch rename to patches/server/1031-optimize-dirt-and-snow-spreading.patch diff --git a/patches/server/1031-Fix-NPE-for-Jukebox-setRecord.patch b/patches/server/1032-Fix-NPE-for-Jukebox-setRecord.patch similarity index 100% rename from patches/server/1031-Fix-NPE-for-Jukebox-setRecord.patch rename to patches/server/1032-Fix-NPE-for-Jukebox-setRecord.patch diff --git a/patches/server/1032-Fix-CraftWorld-isChunkGenerated.patch b/patches/server/1033-Fix-CraftWorld-isChunkGenerated.patch similarity index 100% rename from patches/server/1032-Fix-CraftWorld-isChunkGenerated.patch rename to patches/server/1033-Fix-CraftWorld-isChunkGenerated.patch diff --git a/patches/server/1033-Add-debug-for-chunk-system-unload-crash.patch b/patches/server/1034-Add-debug-for-chunk-system-unload-crash.patch similarity index 100% rename from patches/server/1033-Add-debug-for-chunk-system-unload-crash.patch rename to patches/server/1034-Add-debug-for-chunk-system-unload-crash.patch diff --git a/work/Bukkit b/work/Bukkit index 2b4b6d14241d..e86f4dc4bb89 160000 --- a/work/Bukkit +++ b/work/Bukkit @@ -1 +1 @@ -Subproject commit 2b4b6d14241d3d96eb6b7d1888176146dc5895d4 +Subproject commit e86f4dc4bb897d2ad627763e46c9ed08b090f0f3 diff --git a/work/CraftBukkit b/work/CraftBukkit index 68603b1c1162..c3ceeb6f79b4 160000 --- a/work/CraftBukkit +++ b/work/CraftBukkit @@ -1 +1 @@ -Subproject commit 68603b1c1162f168efdfe8d989d8795587ef9842 +Subproject commit c3ceeb6f79b4258d3c966f34aeafb7ca6d72e41a diff --git a/work/Spigot b/work/Spigot index 146439e88cdd..491f36750240 160000 --- a/work/Spigot +++ b/work/Spigot @@ -1 +1 @@ -Subproject commit 146439e88cdda2de5ce54c2a9d6a6cdd9aa8bc1b +Subproject commit 491f36750240694ded097bb893aa03d5f7bb81d8 From c15de9fd86da93fb9f90c80d2e8136a203002b11 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sat, 6 Jul 2024 00:46:53 +0200 Subject: [PATCH 2/5] Fix wrong intend in handled tags patch --- ...ve-checking-handled-tags-in-itemmeta.patch | 3001 +---------------- .../server/0970-General-ItemMeta-fixes.patch | 480 ++- ...977-Fix-equipment-slot-and-group-API.patch | 30 +- 3 files changed, 330 insertions(+), 3181 deletions(-) diff --git a/patches/server/0969-improve-checking-handled-tags-in-itemmeta.patch b/patches/server/0969-improve-checking-handled-tags-in-itemmeta.patch index 8656622c15f2..42263a75ded9 100644 --- a/patches/server/0969-improve-checking-handled-tags-in-itemmeta.patch +++ b/patches/server/0969-improve-checking-handled-tags-in-itemmeta.patch @@ -451,7 +451,7 @@ index 8c1d2d0521da52f9a1262f5433da21700b9b0454..9600b23666668d7d581e2920a4e03e59 getOrEmpty(tag, CraftMetaFirework.FIREWORKS).ifPresent((fireworks) -> { this.power = fireworks.flightDuration(); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index d29b8c6851aad227eb8f12012903e0ddd5531755..11c6c8d9c14fb31d1819a5c61e3b743b0b6c6d65 100644 +index d29b8c6851aad227eb8f12012903e0ddd5531755..58da8cb19a8444c634cbc1f39e93503ca8e2ecab 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -346,7 +346,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { @@ -463,20 +463,10 @@ index d29b8c6851aad227eb8f12012903e0ddd5531755..11c6c8d9c14fb31d1819a5c61e3b743b CraftMetaItem.getOrEmpty(tag, CraftMetaItem.NAME).ifPresent((component) -> { this.displayName = component; }); -@@ -457,1657 +457,1672 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +@@ -457,12 +457,19 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { }); // Paper end - fix ItemFlags -- Set, Optional>> keys = tag.entrySet(); -- for (Map.Entry, Optional> key : keys) { -- // Paper start - don't lose unhandled tags -- if (key.getValue().isEmpty()) { -- this.unhandledTags.remove(key.getKey()); -- } else if (!CraftMetaItem.getHandledTags().contains(key.getKey())) { -- // Paper end - don't lose unhandled tags -- key.getValue().ifPresent((value) -> { -- this.unhandledTags.set((DataComponentType) key.getKey(), value); -- }); + // Paper start - improve checking handled data component types + Set> handledTags = getTopLevelHandledDcts(this.getClass()); + if (extraHandledTags != null) { @@ -484,2835 +474,20 @@ index d29b8c6851aad227eb8f12012903e0ddd5531755..11c6c8d9c14fb31d1819a5c61e3b743b + handledTags = extraHandledTags; + } + // Paper end - improve checking handled data component types -+ Set, Optional>> keys = tag.entrySet(); -+ for (Map.Entry, Optional> key : keys) { -+ // Paper start - don't lose unhandled tags -+ if (key.getValue().isEmpty()) { -+ this.unhandledTags.remove(key.getKey()); -+ } else if (!handledTags.contains(key.getKey())) { // Paper - improve checking handled data component types -+ // Paper end - don't lose unhandled tags -+ key.getValue().ifPresent((value) -> { -+ this.unhandledTags.set((DataComponentType) key.getKey(), value); -+ }); -+ } -+ -+ if (key.getValue().isEmpty()) { -+ this.removedTags.add(key.getKey()); -+ } - } -+ } -+ -+ static EnchantmentMap buildEnchantments(ItemEnchantments tag) { // Paper -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper -+ -+ tag.entrySet().forEach((entry) -> { -+ Holder id = entry.getKey(); -+ int level = entry.getIntValue(); -+ -+ Enchantment enchant = CraftEnchantment.minecraftHolderToBukkit(id); -+ if (enchant != null) { -+ enchantments.put(enchant, level); -+ } -+ }); -+ -+ return enchantments; -+ } -+ -+ static Multimap buildModifiers(ItemAttributeModifiers tag) { -+ Multimap modifiers = LinkedHashMultimap.create(); -+ List mods = tag.modifiers(); -+ int size = mods.size(); -+ -+ for (int i = 0; i < size; i++) { -+ ItemAttributeModifiers.Entry entry = mods.get(i); -+ net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = entry.modifier(); -+ if (nmsModifier == null) { -+ continue; -+ } -+ -+ AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); -+ -+ Attribute attribute = CraftAttribute.minecraftHolderToBukkit(entry.attribute()); -+ if (attribute == null) { -+ continue; -+ } -+ -+ if (entry.slot() != null) { -+ EquipmentSlotGroup slotName = entry.slot(); -+ if (slotName == null) { -+ modifiers.put(attribute, attribMod); -+ continue; -+ } -+ -+ org.bukkit.inventory.EquipmentSlotGroup slot = null; -+ try { -+ slot = CraftEquipmentSlot.getSlot(slotName); -+ } catch (IllegalArgumentException ex) { -+ // SPIGOT-4551 - Slot is invalid, should really match nothing but this is undefined behaviour anyway -+ } -+ -+ if (slot == null) { -+ modifiers.put(attribute, attribMod); -+ continue; -+ } - -- if (key.getValue().isEmpty()) { -- this.removedTags.add(key.getKey()); -+ attribMod = new AttributeModifier(attribMod.getKey(), attribMod.getAmount(), attribMod.getOperation(), slot); -+ } -+ modifiers.put(attribute, attribMod); - } -+ return modifiers; - } -- } - -- static EnchantmentMap buildEnchantments(ItemEnchantments tag) { // Paper -- EnchantmentMap enchantments = new EnchantmentMap(); // Paper -+ CraftMetaItem(Map map) { -+ this.displayName = CraftChatMessage.fromJSONOrString(SerializableMeta.getString(map, CraftMetaItem.NAME.BUKKIT, true), true, false); -+ this.itemName = CraftChatMessage.fromJSONOrNull(SerializableMeta.getString(map, CraftMetaItem.ITEM_NAME.BUKKIT, true)); - -- tag.entrySet().forEach((entry) -> { -- Holder id = entry.getKey(); -- int level = entry.getIntValue(); -+ Iterable lore = SerializableMeta.getObject(Iterable.class, map, CraftMetaItem.LORE.BUKKIT, true); -+ if (lore != null) { -+ CraftMetaItem.safelyAdd(lore, this.lore = new ArrayList(), true); -+ } - -- Enchantment enchant = CraftEnchantment.minecraftHolderToBukkit(id); -- if (enchant != null) { -- enchantments.put(enchant, level); -+ Integer customModelData = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.CUSTOM_MODEL_DATA.BUKKIT, true); -+ if (customModelData != null) { -+ this.setCustomModelData(customModelData); - } -- }); - -- return enchantments; -- } -+ Object blockData = SerializableMeta.getObject(Object.class, map, CraftMetaItem.BLOCK_DATA.BUKKIT, true); -+ if (blockData != null) { -+ Map mapBlockData = new HashMap<>(); - -- static Multimap buildModifiers(ItemAttributeModifiers tag) { -- Multimap modifiers = LinkedHashMultimap.create(); -- List mods = tag.modifiers(); -- int size = mods.size(); -+ CompoundTag nbtBlockData = (CompoundTag) CraftNBTTagConfigSerializer.deserialize(blockData); -+ for (String key : nbtBlockData.getAllKeys()) { -+ mapBlockData.put(key, nbtBlockData.getString(key)); -+ } - -- for (int i = 0; i < size; i++) { -- ItemAttributeModifiers.Entry entry = mods.get(i); -- net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = entry.modifier(); -- if (nmsModifier == null) { -- continue; -+ this.blockData = mapBlockData; - } - -- AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); -+ this.enchantments = CraftMetaItem.buildEnchantments(map, CraftMetaItem.ENCHANTMENTS); -+ this.attributeModifiers = CraftMetaItem.buildModifiers(map, CraftMetaItem.ATTRIBUTES); - -- Attribute attribute = CraftAttribute.minecraftHolderToBukkit(entry.attribute()); -- if (attribute == null) { -- continue; -+ Integer repairCost = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.REPAIR.BUKKIT, true); -+ if (repairCost != null) { -+ this.setRepairCost(repairCost); - } - -- if (entry.slot() != null) { -- EquipmentSlotGroup slotName = entry.slot(); -- if (slotName == null) { -- modifiers.put(attribute, attribMod); -- continue; -+ Iterable hideFlags = SerializableMeta.getObject(Iterable.class, map, CraftMetaItem.HIDEFLAGS.BUKKIT, true); -+ if (hideFlags != null) { -+ for (Object hideFlagObject : hideFlags) { -+ String hideFlagString = (String) hideFlagObject; -+ try { -+ ItemFlag hideFlatEnum = CraftItemFlag.stringToBukkit(hideFlagString); -+ this.addItemFlags(hideFlatEnum); -+ } catch (IllegalArgumentException ex) { -+ // Ignore when we got a old String which does not map to a Enum value anymore -+ } - } -+ } - -- org.bukkit.inventory.EquipmentSlotGroup slot = null; -- try { -- slot = CraftEquipmentSlot.getSlot(slotName); -- } catch (IllegalArgumentException ex) { -- // SPIGOT-4551 - Slot is invalid, should really match nothing but this is undefined behaviour anyway -- } -+ Boolean hideTooltip = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.HIDE_TOOLTIP.BUKKIT, true); -+ if (hideTooltip != null) { -+ this.setHideTooltip(hideTooltip); -+ } - -- if (slot == null) { -- modifiers.put(attribute, attribMod); -- continue; -- } -+ Boolean unbreakable = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.UNBREAKABLE.BUKKIT, true); -+ if (unbreakable != null) { -+ this.setUnbreakable(unbreakable); -+ } - -- attribMod = new AttributeModifier(attribMod.getKey(), attribMod.getAmount(), attribMod.getOperation(), slot); -+ Boolean enchantmentGlintOverride = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.BUKKIT, true); -+ if (enchantmentGlintOverride != null) { -+ this.setEnchantmentGlintOverride(enchantmentGlintOverride); - } -- modifiers.put(attribute, attribMod); -- } -- return modifiers; -- } - -- CraftMetaItem(Map map) { -- this.displayName = CraftChatMessage.fromJSONOrString(SerializableMeta.getString(map, CraftMetaItem.NAME.BUKKIT, true), true, false); -- this.itemName = CraftChatMessage.fromJSONOrNull(SerializableMeta.getString(map, CraftMetaItem.ITEM_NAME.BUKKIT, true)); -+ Boolean fireResistant = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.FIRE_RESISTANT.BUKKIT, true); -+ if (fireResistant != null) { -+ this.setFireResistant(fireResistant); -+ } - -- Iterable lore = SerializableMeta.getObject(Iterable.class, map, CraftMetaItem.LORE.BUKKIT, true); -- if (lore != null) { -- CraftMetaItem.safelyAdd(lore, this.lore = new ArrayList(), true); -- } -+ Integer maxStackSize = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.MAX_STACK_SIZE.BUKKIT, true); -+ if (maxStackSize != null) { -+ this.setMaxStackSize(maxStackSize); -+ } - -- Integer customModelData = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.CUSTOM_MODEL_DATA.BUKKIT, true); -- if (customModelData != null) { -- this.setCustomModelData(customModelData); -- } -+ String rarity = SerializableMeta.getString(map, CraftMetaItem.RARITY.BUKKIT, true); -+ if (rarity != null) { -+ this.setRarity(ItemRarity.valueOf(rarity)); -+ } - -- Object blockData = SerializableMeta.getObject(Object.class, map, CraftMetaItem.BLOCK_DATA.BUKKIT, true); -- if (blockData != null) { -- Map mapBlockData = new HashMap<>(); -+ CraftFoodComponent food = SerializableMeta.getObject(CraftFoodComponent.class, map, CraftMetaItem.FOOD.BUKKIT, true); -+ if (food != null) { -+ this.setFood(food); -+ } - -- CompoundTag nbtBlockData = (CompoundTag) CraftNBTTagConfigSerializer.deserialize(blockData); -- for (String key : nbtBlockData.getAllKeys()) { -- mapBlockData.put(key, nbtBlockData.getString(key)); -+ CraftToolComponent tool = SerializableMeta.getObject(CraftToolComponent.class, map, CraftMetaItem.TOOL.BUKKIT, true); -+ if (tool != null) { -+ this.setTool(tool); - } - -- this.blockData = mapBlockData; -- } -+ CraftJukeboxComponent jukeboxPlayable = SerializableMeta.getObject(CraftJukeboxComponent.class, map, CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, true); -+ if (jukeboxPlayable != null) { -+ this.setJukeboxPlayable(jukeboxPlayable); -+ } - -- this.enchantments = CraftMetaItem.buildEnchantments(map, CraftMetaItem.ENCHANTMENTS); -- this.attributeModifiers = CraftMetaItem.buildModifiers(map, CraftMetaItem.ATTRIBUTES); -+ Integer damage = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.DAMAGE.BUKKIT, true); -+ if (damage != null) { -+ this.setDamage(damage); -+ } - -- Integer repairCost = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.REPAIR.BUKKIT, true); -- if (repairCost != null) { -- this.setRepairCost(repairCost); -- } -+ Integer maxDamage = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.MAX_DAMAGE.BUKKIT, true); -+ if (maxDamage != null) { -+ this.setMaxDamage(maxDamage); -+ } - -- Iterable hideFlags = SerializableMeta.getObject(Iterable.class, map, CraftMetaItem.HIDEFLAGS.BUKKIT, true); -- if (hideFlags != null) { -- for (Object hideFlagObject : hideFlags) { -- String hideFlagString = (String) hideFlagObject; -+ String internal = SerializableMeta.getString(map, "internal", true); -+ if (internal != null) { -+ ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(internal)); - try { -- ItemFlag hideFlatEnum = CraftItemFlag.stringToBukkit(hideFlagString); -- this.addItemFlags(hideFlatEnum); -- } catch (IllegalArgumentException ex) { -- // Ignore when we got a old String which does not map to a Enum value anymore -+ CompoundTag internalTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); -+ this.deserializeInternal(internalTag, map); -+ } catch (IOException ex) { -+ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); - } - } -- } - -- Boolean hideTooltip = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.HIDE_TOOLTIP.BUKKIT, true); -- if (hideTooltip != null) { -- this.setHideTooltip(hideTooltip); -- } -+ String unhandled = SerializableMeta.getString(map, "unhandled", true); -+ if (unhandled != null) { -+ ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(unhandled)); -+ try { -+ CompoundTag unhandledTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); -+ DataComponentPatch unhandledPatch = DataComponentPatch.CODEC.parse(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), unhandledTag).result().get(); -+ // Paper start -+ CraftMetaItem.getOrEmpty(unhandledPatch, CraftMetaItem.CAN_PLACE_ON).ifPresent(data -> { -+ this.canPlaceOnPredicates = List.copyOf(data.predicates); -+ }); -+ CraftMetaItem.getOrEmpty(unhandledPatch, CraftMetaItem.CAN_BREAK).ifPresent(data -> { -+ this.canBreakPredicates = List.copyOf(data.predicates); -+ }); -+ this.unhandledTags.copy(unhandledPatch.forget(type -> type == CraftMetaItem.CAN_PLACE_ON.TYPE || type == CraftMetaItem.CAN_BREAK.TYPE)); -+ // Paper end -+ -+ for (Entry, Optional> entry : unhandledPatch.entrySet()) { -+ // Move removed unhandled tags to dedicated removedTags -+ if (!entry.getValue().isPresent()) { -+ DataComponentType key = entry.getKey(); -+ -+ this.unhandledTags.clear(key); -+ this.removedTags.add(key); -+ } -+ } -+ } catch (IOException ex) { -+ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ } -+ } - -- Boolean unbreakable = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.UNBREAKABLE.BUKKIT, true); -- if (unbreakable != null) { -- this.setUnbreakable(unbreakable); -- } -+ Iterable removed = SerializableMeta.getObject(Iterable.class, map, "removed", true); -+ if (removed != null) { -+ RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); -+ Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); - -- Boolean enchantmentGlintOverride = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.BUKKIT, true); -- if (enchantmentGlintOverride != null) { -- this.setEnchantmentGlintOverride(enchantmentGlintOverride); -- } -+ for (Object removedObject : removed) { -+ String removedString = (String) removedObject; - -- Boolean fireResistant = SerializableMeta.getObject(Boolean.class, map, CraftMetaItem.FIRE_RESISTANT.BUKKIT, true); -- if (fireResistant != null) { -- this.setFireResistant(fireResistant); -- } -+ DataComponentType component = componentTypeRegistry.get(ResourceLocation.parse(removedString)); -+ if (component != null) { -+ this.removedTags.add(component); -+ } -+ } -+ } - -- Integer maxStackSize = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.MAX_STACK_SIZE.BUKKIT, true); -- if (maxStackSize != null) { -- this.setMaxStackSize(maxStackSize); -- } -+ Object nbtMap = SerializableMeta.getObject(Object.class, map, CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, true); // We read both legacy maps and potential modern snbt strings here -+ if (nbtMap != null) { -+ this.persistentDataContainer.putAll((CompoundTag) CraftNBTTagConfigSerializer.deserialize(nbtMap)); -+ } - -- String rarity = SerializableMeta.getString(map, CraftMetaItem.RARITY.BUKKIT, true); -- if (rarity != null) { -- this.setRarity(ItemRarity.valueOf(rarity)); -+ String custom = SerializableMeta.getString(map, "custom", true); -+ if (custom != null) { -+ ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(custom)); -+ try { -+ this.customTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); -+ } catch (IOException ex) { -+ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ } -+ } - } - -- CraftFoodComponent food = SerializableMeta.getObject(CraftFoodComponent.class, map, CraftMetaItem.FOOD.BUKKIT, true); -- if (food != null) { -- this.setFood(food); -+ void deserializeInternal(CompoundTag tag, Object context) { -+ // SPIGOT-4576: Need to migrate from internal to proper data -+ if (tag.contains(CraftMetaItem.ATTRIBUTES.NBT, CraftMagicNumbers.NBT.TAG_LIST)) { -+ this.attributeModifiers = CraftMetaItem.buildModifiersLegacy(tag, CraftMetaItem.ATTRIBUTES); -+ } - } - -- CraftToolComponent tool = SerializableMeta.getObject(CraftToolComponent.class, map, CraftMetaItem.TOOL.BUKKIT, true); -- if (tool != null) { -- this.setTool(tool); -- } -+ private static Multimap buildModifiersLegacy(CompoundTag tag, ItemMetaKey key) { -+ Multimap modifiers = LinkedHashMultimap.create(); -+ if (!tag.contains(key.NBT, CraftMagicNumbers.NBT.TAG_LIST)) { -+ return modifiers; -+ } -+ ListTag mods = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); -+ int size = mods.size(); - -- CraftJukeboxComponent jukeboxPlayable = SerializableMeta.getObject(CraftJukeboxComponent.class, map, CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, true); -- if (jukeboxPlayable != null) { -- this.setJukeboxPlayable(jukeboxPlayable); -- } -+ for (int i = 0; i < size; i++) { -+ CompoundTag entry = mods.getCompound(i); -+ if (entry.isEmpty()) { -+ // entry is not an actual NBTTagCompound. getCompound returns empty NBTTagCompound in that case -+ continue; -+ } -+ net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = net.minecraft.world.entity.ai.attributes.AttributeModifier.load(entry); -+ if (nmsModifier == null) { -+ continue; -+ } - -- Integer damage = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.DAMAGE.BUKKIT, true); -- if (damage != null) { -- this.setDamage(damage); -- } -+ AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); - -- Integer maxDamage = SerializableMeta.getObject(Integer.class, map, CraftMetaItem.MAX_DAMAGE.BUKKIT, true); -- if (maxDamage != null) { -- this.setMaxDamage(maxDamage); -+ String attributeName = org.bukkit.craftbukkit.attribute.CraftAttributeMap.convertIfNeeded(entry.getString(CraftMetaItem.ATTRIBUTES_IDENTIFIER.NBT)); // Paper -+ if (attributeName == null || attributeName.isEmpty()) { -+ continue; -+ } -+ -+ Attribute attribute = CraftAttribute.stringToBukkit(attributeName); -+ if (attribute == null) { -+ continue; -+ } -+ -+ if (entry.contains(CraftMetaItem.ATTRIBUTES_SLOT.NBT, CraftMagicNumbers.NBT.TAG_STRING)) { -+ String slotName = entry.getString(CraftMetaItem.ATTRIBUTES_SLOT.NBT); -+ if (slotName == null || slotName.isEmpty()) { -+ modifiers.put(attribute, attribMod); -+ continue; -+ } -+ -+ EquipmentSlot slot = null; -+ try { -+ slot = CraftEquipmentSlot.getSlot(net.minecraft.world.entity.EquipmentSlot.byName(slotName.toLowerCase(Locale.ROOT))); -+ } catch (IllegalArgumentException ex) { -+ // SPIGOT-4551 - Slot is invalid, should really match nothing but this is undefined behaviour anyway -+ } -+ -+ if (slot == null) { -+ modifiers.put(attribute, attribMod); -+ continue; -+ } -+ -+ attribMod = new AttributeModifier(attribMod.getKey(), attribMod.getAmount(), attribMod.getOperation(), slot.getGroup()); -+ } -+ modifiers.put(attribute, attribMod); -+ } -+ return modifiers; - } - -- String internal = SerializableMeta.getString(map, "internal", true); -- if (internal != null) { -- ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(internal)); -- try { -- CompoundTag internalTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); -- this.deserializeInternal(internalTag, map); -- } catch (IOException ex) { -- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper -+ Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); -+ if (ench == null) { -+ return null; -+ } -+ -+ EnchantmentMap enchantments = new EnchantmentMap(); // Paper -+ for (Map.Entry entry : ench.entrySet()) { -+ Enchantment enchantment = CraftEnchantment.stringToBukkit(entry.getKey().toString()); -+ if ((enchantment != null) && (entry.getValue() instanceof Integer)) { -+ enchantments.put(enchantment, (Integer) entry.getValue()); -+ } - } -+ -+ return enchantments; - } - -- String unhandled = SerializableMeta.getString(map, "unhandled", true); -- if (unhandled != null) { -- ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(unhandled)); -- try { -- CompoundTag unhandledTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); -- DataComponentPatch unhandledPatch = DataComponentPatch.CODEC.parse(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), unhandledTag).result().get(); -- // Paper start -- CraftMetaItem.getOrEmpty(unhandledPatch, CraftMetaItem.CAN_PLACE_ON).ifPresent(data -> { -- this.canPlaceOnPredicates = List.copyOf(data.predicates); -- }); -- CraftMetaItem.getOrEmpty(unhandledPatch, CraftMetaItem.CAN_BREAK).ifPresent(data -> { -- this.canBreakPredicates = List.copyOf(data.predicates); -- }); -- this.unhandledTags.copy(unhandledPatch.forget(type -> type == CraftMetaItem.CAN_PLACE_ON.TYPE || type == CraftMetaItem.CAN_BREAK.TYPE)); -- // Paper end -+ static Multimap buildModifiers(Map map, ItemMetaKey key) { -+ Map mods = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); -+ Multimap result = LinkedHashMultimap.create(); -+ if (mods == null) { -+ return result; -+ } - -- for (Entry, Optional> entry : unhandledPatch.entrySet()) { -- // Move removed unhandled tags to dedicated removedTags -- if (!entry.getValue().isPresent()) { -- DataComponentType key = entry.getKey(); -+ for (Object obj : mods.keySet()) { -+ if (!(obj instanceof String)) { -+ continue; -+ } -+ String attributeName = (String) obj; -+ if (Strings.isNullOrEmpty(attributeName)) { -+ continue; -+ } -+ List list = SerializableMeta.getObject(List.class, mods, attributeName, true); -+ if (list == null || list.isEmpty()) { -+ return result; -+ } - -- this.unhandledTags.clear(key); -- this.removedTags.add(key); -+ for (Object o : list) { -+ if (!(o instanceof AttributeModifier)) { // this catches null -+ continue; - } -+ AttributeModifier modifier = (AttributeModifier) o; -+ Attribute attribute = CraftAttribute.stringToBukkit(attributeName); -+ if (attribute == null) { -+ continue; -+ } -+ -+ result.put(attribute, modifier); - } -- } catch (IOException ex) { -- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); - } -+ return result; - } - -- Iterable removed = SerializableMeta.getObject(Iterable.class, map, "removed", true); -- if (removed != null) { -- RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); -- Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); -+ @Overridden -+ void applyToItem(CraftMetaItem.Applicator itemTag) { -+ if (this.hasDisplayName()) { -+ itemTag.put(CraftMetaItem.NAME, this.displayName); -+ } -+ -+ if (this.hasItemName()) { -+ itemTag.put(CraftMetaItem.ITEM_NAME, this.itemName); -+ } - -- for (Object removedObject : removed) { -- String removedString = (String) removedObject; -+ if (this.lore != null) { -+ itemTag.put(CraftMetaItem.LORE, new ItemLore(this.lore)); -+ } -+ -+ if (this.hasCustomModelData()) { -+ itemTag.put(CraftMetaItem.CUSTOM_MODEL_DATA, new CustomModelData(this.customModelData)); -+ } - -- DataComponentType component = componentTypeRegistry.get(ResourceLocation.parse(removedString)); -- if (component != null) { -- this.removedTags.add(component); -+ if (this.hasBlockData()) { -+ itemTag.put(CraftMetaItem.BLOCK_DATA, new BlockItemStateProperties(this.blockData)); -+ } -+ -+ if (this.hideFlag != 0) { -+ if (this.hasItemFlag(ItemFlag.HIDE_ADDITIONAL_TOOLTIP)) { -+ itemTag.put(CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP, Unit.INSTANCE); - } - } -- } - -- Object nbtMap = SerializableMeta.getObject(Object.class, map, CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, true); // We read both legacy maps and potential modern snbt strings here -- if (nbtMap != null) { -- this.persistentDataContainer.putAll((CompoundTag) CraftNBTTagConfigSerializer.deserialize(nbtMap)); -- } -+ this.applyEnchantments(this.enchantments, itemTag, CraftMetaItem.ENCHANTMENTS, ItemFlag.HIDE_ENCHANTS); -+ this.applyModifiers(this.attributeModifiers, itemTag); - -- String custom = SerializableMeta.getString(map, "custom", true); -- if (custom != null) { -- ByteArrayInputStream buf = new ByteArrayInputStream(Base64.getDecoder().decode(custom)); -- try { -- this.customTag = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); -- } catch (IOException ex) { -- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ if (this.hasRepairCost()) { -+ itemTag.put(CraftMetaItem.REPAIR, this.repairCost); - } -- } -- } - -- void deserializeInternal(CompoundTag tag, Object context) { -- // SPIGOT-4576: Need to migrate from internal to proper data -- if (tag.contains(CraftMetaItem.ATTRIBUTES.NBT, CraftMagicNumbers.NBT.TAG_LIST)) { -- this.attributeModifiers = CraftMetaItem.buildModifiersLegacy(tag, CraftMetaItem.ATTRIBUTES); -- } -- } -+ if (this.isHideTooltip()) { -+ itemTag.put(CraftMetaItem.HIDE_TOOLTIP, Unit.INSTANCE); -+ } - -- private static Multimap buildModifiersLegacy(CompoundTag tag, ItemMetaKey key) { -- Multimap modifiers = LinkedHashMultimap.create(); -- if (!tag.contains(key.NBT, CraftMagicNumbers.NBT.TAG_LIST)) { -- return modifiers; -- } -- ListTag mods = tag.getList(key.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); -- int size = mods.size(); -+ if (this.isUnbreakable()) { -+ itemTag.put(CraftMetaItem.UNBREAKABLE, new Unbreakable(!this.hasItemFlag(ItemFlag.HIDE_UNBREAKABLE))); -+ } - -- for (int i = 0; i < size; i++) { -- CompoundTag entry = mods.getCompound(i); -- if (entry.isEmpty()) { -- // entry is not an actual NBTTagCompound. getCompound returns empty NBTTagCompound in that case -- continue; -+ if (this.hasEnchantmentGlintOverride()) { -+ itemTag.put(CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE, this.getEnchantmentGlintOverride()); - } -- net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = net.minecraft.world.entity.ai.attributes.AttributeModifier.load(entry); -- if (nmsModifier == null) { -- continue; -+ -+ if (this.isFireResistant()) { -+ itemTag.put(CraftMetaItem.FIRE_RESISTANT, Unit.INSTANCE); - } - -- AttributeModifier attribMod = CraftAttributeInstance.convert(nmsModifier); -+ if (this.hasMaxStackSize()) { -+ itemTag.put(CraftMetaItem.MAX_STACK_SIZE, this.maxStackSize); -+ } - -- String attributeName = org.bukkit.craftbukkit.attribute.CraftAttributeMap.convertIfNeeded(entry.getString(CraftMetaItem.ATTRIBUTES_IDENTIFIER.NBT)); // Paper -- if (attributeName == null || attributeName.isEmpty()) { -- continue; -+ if (this.hasRarity()) { -+ itemTag.put(CraftMetaItem.RARITY, Rarity.valueOf(this.rarity.name())); - } - -- Attribute attribute = CraftAttribute.stringToBukkit(attributeName); -- if (attribute == null) { -- continue; -+ if (this.hasFood()) { -+ itemTag.put(CraftMetaItem.FOOD, this.food.getHandle()); - } - -- if (entry.contains(CraftMetaItem.ATTRIBUTES_SLOT.NBT, CraftMagicNumbers.NBT.TAG_STRING)) { -- String slotName = entry.getString(CraftMetaItem.ATTRIBUTES_SLOT.NBT); -- if (slotName == null || slotName.isEmpty()) { -- modifiers.put(attribute, attribMod); -- continue; -- } -+ if (this.hasTool()) { -+ itemTag.put(CraftMetaItem.TOOL, this.tool.getHandle()); -+ } - -- EquipmentSlot slot = null; -- try { -- slot = CraftEquipmentSlot.getSlot(net.minecraft.world.entity.EquipmentSlot.byName(slotName.toLowerCase(Locale.ROOT))); -- } catch (IllegalArgumentException ex) { -- // SPIGOT-4551 - Slot is invalid, should really match nothing but this is undefined behaviour anyway -+ if (this.hasJukeboxPlayable()) { -+ itemTag.put(CraftMetaItem.JUKEBOX_PLAYABLE, this.jukebox.getHandle()); -+ } -+ -+ if (this.hasDamage()) { -+ itemTag.put(CraftMetaItem.DAMAGE, this.damage); -+ } -+ -+ if (this.hasMaxDamage()) { -+ itemTag.put(CraftMetaItem.MAX_DAMAGE, this.maxDamage); -+ } -+ -+ // Paper start -+ if (this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty()) { -+ itemTag.put(CraftMetaItem.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON))); -+ } -+ if (this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty()) { -+ itemTag.put(CraftMetaItem.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS))); -+ } -+ // Paper end -+ -+ for (Map.Entry, Optional> e : this.unhandledTags.build().entrySet()) { -+ e.getValue().ifPresentOrElse((value) -> { -+ itemTag.builder.set((DataComponentType) e.getKey(), value); -+ }, () -> itemTag.remove(e.getKey())); -+ } -+ -+ for (DataComponentType removed : this.removedTags) { -+ if (!itemTag.builder.isSet(removed)) { -+ itemTag.builder.remove(removed); - } -+ } - -- if (slot == null) { -- modifiers.put(attribute, attribMod); -- continue; -+ CompoundTag customTag = (this.customTag != null) ? this.customTag.copy() : null; -+ if (!this.persistentDataContainer.isEmpty()) { -+ CompoundTag bukkitCustomCompound = new CompoundTag(); -+ Map rawPublicMap = this.persistentDataContainer.getRaw(); -+ -+ for (Map.Entry nbtBaseEntry : rawPublicMap.entrySet()) { -+ bukkitCustomCompound.put(nbtBaseEntry.getKey(), nbtBaseEntry.getValue()); - } - -- attribMod = new AttributeModifier(attribMod.getKey(), attribMod.getAmount(), attribMod.getOperation(), slot.getGroup()); -+ if (customTag == null) { -+ customTag = new CompoundTag(); -+ } -+ customTag.put(CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, bukkitCustomCompound); - } -- modifiers.put(attribute, attribMod); -- } -- return modifiers; -- } - -- static EnchantmentMap buildEnchantments(Map map, ItemMetaKey key) { // Paper -- Map ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); -- if (ench == null) { -- return null; -+ if (customTag != null) { -+ itemTag.put(CraftMetaItem.CUSTOM_DATA, CustomData.of(customTag)); -+ } - } - -- EnchantmentMap enchantments = new EnchantmentMap(); // Paper -- for (Map.Entry entry : ench.entrySet()) { -- Enchantment enchantment = CraftEnchantment.stringToBukkit(entry.getKey().toString()); -- if ((enchantment != null) && (entry.getValue() instanceof Integer)) { -- enchantments.put(enchantment, (Integer) entry.getValue()); -+ void applyEnchantments(Map enchantments, CraftMetaItem.Applicator tag, ItemMetaKeyType key, ItemFlag itemFlag) { -+ if (enchantments == null) { -+ return; - } -- } - -- return enchantments; -- } -+ ItemEnchantments.Mutable list = new ItemEnchantments.Mutable(ItemEnchantments.EMPTY); - -- static Multimap buildModifiers(Map map, ItemMetaKey key) { -- Map mods = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); -- Multimap result = LinkedHashMultimap.create(); -- if (mods == null) { -- return result; -+ for (Map.Entry entry : enchantments.entrySet()) { -+ list.set(CraftEnchantment.bukkitToMinecraftHolder(entry.getKey()), entry.getValue()); -+ } -+ -+ list.showInTooltip = !this.hasItemFlag(itemFlag); -+ tag.put(key, list.toImmutable()); - } - -- for (Object obj : mods.keySet()) { -- if (!(obj instanceof String)) { -- continue; -- } -- String attributeName = (String) obj; -- if (Strings.isNullOrEmpty(attributeName)) { -- continue; -- } -- List list = SerializableMeta.getObject(List.class, mods, attributeName, true); -- if (list == null || list.isEmpty()) { -- return result; -+ void applyModifiers(Multimap modifiers, CraftMetaItem.Applicator tag) { -+ if (modifiers == null || modifiers.isEmpty()) { -+ if (this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES)) { -+ tag.put(CraftMetaItem.ATTRIBUTES, new ItemAttributeModifiers(Collections.emptyList(), false)); -+ } -+ return; - } - -- for (Object o : list) { -- if (!(o instanceof AttributeModifier)) { // this catches null -+ ItemAttributeModifiers.Builder list = ItemAttributeModifiers.builder(); -+ for (Map.Entry entry : modifiers.entries()) { -+ if (entry.getKey() == null || entry.getValue() == null) { - continue; - } -- AttributeModifier modifier = (AttributeModifier) o; -- Attribute attribute = CraftAttribute.stringToBukkit(attributeName); -- if (attribute == null) { -+ net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = CraftAttributeInstance.convert(entry.getValue()); -+ -+ Holder name = CraftAttribute.bukkitToMinecraftHolder(entry.getKey()); -+ if (name == null) { - continue; - } - -- result.put(attribute, modifier); -+ EquipmentSlotGroup group = CraftEquipmentSlot.getNMSGroup(entry.getValue().getSlotGroup()); -+ list.add(name, nmsModifier, group); - } -+ tag.put(CraftMetaItem.ATTRIBUTES, list.build().withTooltip(!this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES))); - } -- return result; -- } - -- @Overridden -- void applyToItem(CraftMetaItem.Applicator itemTag) { -- if (this.hasDisplayName()) { -- itemTag.put(CraftMetaItem.NAME, this.displayName); -- } -+ boolean applicableTo(Material type) { -+ if (type == Material.AIR || !type.isItem()) { -+ return false; -+ } - -- if (this.hasItemName()) { -- itemTag.put(CraftMetaItem.ITEM_NAME, this.itemName); -- } -+ if (this.getClass() == CraftMetaItem.class) { -+ return true; -+ } - -- if (this.lore != null) { -- itemTag.put(CraftMetaItem.LORE, new ItemLore(this.lore)); -+ // We assume that the corresponding bukkit interface is always the first one -+ return type.asItemType().getItemMetaClass() == this.getClass().getInterfaces()[0]; - } - -- if (this.hasCustomModelData()) { -- itemTag.put(CraftMetaItem.CUSTOM_MODEL_DATA, new CustomModelData(this.customModelData)); -+ @Overridden -+ boolean isEmpty() { -+ return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper - } - -- if (this.hasBlockData()) { -- itemTag.put(CraftMetaItem.BLOCK_DATA, new BlockItemStateProperties(this.blockData)); -+ // Paper start -+ @Override -+ public net.kyori.adventure.text.Component displayName() { -+ return displayName == null ? null : io.papermc.paper.adventure.PaperAdventure.asAdventure(displayName); - } - -- if (this.hideFlag != 0) { -- if (this.hasItemFlag(ItemFlag.HIDE_ADDITIONAL_TOOLTIP)) { -- itemTag.put(CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP, Unit.INSTANCE); -- } -+ @Override -+ public void displayName(final net.kyori.adventure.text.Component displayName) { -+ this.displayName = displayName == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName); - } -+ // Paper end - -- this.applyEnchantments(this.enchantments, itemTag, CraftMetaItem.ENCHANTMENTS, ItemFlag.HIDE_ENCHANTS); -- this.applyModifiers(this.attributeModifiers, itemTag); -- -- if (this.hasRepairCost()) { -- itemTag.put(CraftMetaItem.REPAIR, this.repairCost); -+ @Override -+ public String getDisplayName() { -+ return CraftChatMessage.fromComponent(this.displayName); - } - -- if (this.isHideTooltip()) { -- itemTag.put(CraftMetaItem.HIDE_TOOLTIP, Unit.INSTANCE); -+ // Paper start -+ @Override -+ public net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent() { -+ return displayName == null ? new net.md_5.bungee.api.chat.BaseComponent[0] : net.md_5.bungee.chat.ComponentSerializer.parse(CraftChatMessage.toJSON(displayName)); -+ } -+ // Paper end -+ @Override -+ public final void setDisplayName(String name) { -+ this.displayName = CraftChatMessage.fromStringOrNull(name); - } - -- if (this.isUnbreakable()) { -- itemTag.put(CraftMetaItem.UNBREAKABLE, new Unbreakable(!this.hasItemFlag(ItemFlag.HIDE_UNBREAKABLE))); -+ // Paper start -+ @Override -+ public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { -+ this.displayName = CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(component)); -+ } -+ // Paper end -+ @Override -+ public boolean hasDisplayName() { -+ return this.displayName != null; - } - -- if (this.hasEnchantmentGlintOverride()) { -- itemTag.put(CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE, this.getEnchantmentGlintOverride()); -+ @Override -+ public String getItemName() { -+ return CraftChatMessage.fromComponent(this.itemName); - } - -- if (this.isFireResistant()) { -- itemTag.put(CraftMetaItem.FIRE_RESISTANT, Unit.INSTANCE); -+ @Override -+ public final void setItemName(String name) { -+ this.itemName = CraftChatMessage.fromStringOrNull(name); - } - -- if (this.hasMaxStackSize()) { -- itemTag.put(CraftMetaItem.MAX_STACK_SIZE, this.maxStackSize); -+ @Override -+ public boolean hasItemName() { -+ return this.itemName != null; - } - -- if (this.hasRarity()) { -- itemTag.put(CraftMetaItem.RARITY, Rarity.valueOf(this.rarity.name())); -+ // Paper start - Adventure -+ @Override -+ public net.kyori.adventure.text.Component itemName() { -+ return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.itemName); - } - -- if (this.hasFood()) { -- itemTag.put(CraftMetaItem.FOOD, this.food.getHandle()); -+ @Override -+ public void itemName(final net.kyori.adventure.text.Component name) { -+ this.itemName = io.papermc.paper.adventure.PaperAdventure.asVanilla(name); - } -+ // Paper end - Adventure - -- if (this.hasTool()) { -- itemTag.put(CraftMetaItem.TOOL, this.tool.getHandle()); -+ @Override -+ public String getLocalizedName() { -+ return this.getDisplayName(); - } - -- if (this.hasJukeboxPlayable()) { -- itemTag.put(CraftMetaItem.JUKEBOX_PLAYABLE, this.jukebox.getHandle()); -+ @Override -+ public void setLocalizedName(String name) { - } - -- if (this.hasDamage()) { -- itemTag.put(CraftMetaItem.DAMAGE, this.damage); -+ @Override -+ public boolean hasLocalizedName() { -+ return false; - } - -- if (this.hasMaxDamage()) { -- itemTag.put(CraftMetaItem.MAX_DAMAGE, this.maxDamage); -+ @Override -+ public boolean hasLore() { -+ return this.lore != null && !this.lore.isEmpty(); - } - - // Paper start -- if (this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty()) { -- itemTag.put(CraftMetaItem.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON))); -+ @Override -+ public List lore() { -+ return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(this.lore) : null; - } -- if (this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty()) { -- itemTag.put(CraftMetaItem.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS))); -+ -+ @Override -+ public void lore(final List lore) { -+ this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(lore) : null; - } - // Paper end - -- for (Map.Entry, Optional> e : this.unhandledTags.build().entrySet()) { -- e.getValue().ifPresentOrElse((value) -> { -- itemTag.builder.set((DataComponentType) e.getKey(), value); -- }, () -> itemTag.remove(e.getKey())); -+ @Override -+ public boolean hasRepairCost() { -+ return this.repairCost > 0; -+ } -+ -+ @Override -+ public boolean hasEnchant(Enchantment ench) { -+ Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); -+ return this.hasEnchants() && this.enchantments.containsKey(ench); - } - -- for (DataComponentType removed : this.removedTags) { -- if (!itemTag.builder.isSet(removed)) { -- itemTag.builder.remove(removed); -+ @Override -+ public int getEnchantLevel(Enchantment ench) { -+ Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); -+ Integer level = this.hasEnchants() ? this.enchantments.get(ench) : null; -+ if (level == null) { -+ return 0; - } -+ return level; - } - -- CompoundTag customTag = (this.customTag != null) ? this.customTag.copy() : null; -- if (!this.persistentDataContainer.isEmpty()) { -- CompoundTag bukkitCustomCompound = new CompoundTag(); -- Map rawPublicMap = this.persistentDataContainer.getRaw(); -+ @Override -+ public Map getEnchants() { -+ return this.hasEnchants() ? ImmutableSortedMap.copyOfSorted(this.enchantments) : ImmutableMap.of(); // Paper -+ } - -- for (Map.Entry nbtBaseEntry : rawPublicMap.entrySet()) { -- bukkitCustomCompound.put(nbtBaseEntry.getKey(), nbtBaseEntry.getValue()); -+ @Override -+ public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { -+ Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); -+ if (this.enchantments == null) { -+ this.enchantments = new EnchantmentMap(); // Paper - } - -- if (customTag == null) { -- customTag = new CompoundTag(); -+ if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { -+ Integer old = this.enchantments.put(ench, level); -+ return old == null || old != level; - } -- customTag.put(CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, bukkitCustomCompound); -+ return false; - } - -- if (customTag != null) { -- itemTag.put(CraftMetaItem.CUSTOM_DATA, CustomData.of(customTag)); -+ @Override -+ public boolean removeEnchant(Enchantment ench) { -+ Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); -+ boolean enchantmentRemoved = this.hasEnchants() && this.enchantments.remove(ench) != null; -+ // If we no longer have any enchantments, then clear enchantment tag -+ if (enchantmentRemoved && this.enchantments.isEmpty()) { -+ this.enchantments = null; -+ } -+ return enchantmentRemoved; - } -- } - -- void applyEnchantments(Map enchantments, CraftMetaItem.Applicator tag, ItemMetaKeyType key, ItemFlag itemFlag) { -- if (enchantments == null) { -- return; -+ @Override -+ public void removeEnchantments() { -+ if (this.hasEnchants()) { -+ this.enchantments.clear(); -+ } - } - -- ItemEnchantments.Mutable list = new ItemEnchantments.Mutable(ItemEnchantments.EMPTY); -- -- for (Map.Entry entry : enchantments.entrySet()) { -- list.set(CraftEnchantment.bukkitToMinecraftHolder(entry.getKey()), entry.getValue()); -+ @Override -+ public boolean hasEnchants() { -+ return !(this.enchantments == null || this.enchantments.isEmpty()); - } - -- list.showInTooltip = !this.hasItemFlag(itemFlag); -- tag.put(key, list.toImmutable()); -- } -+ @Override -+ public boolean hasConflictingEnchant(Enchantment ench) { -+ return CraftMetaItem.checkConflictingEnchants(this.enchantments, ench); -+ } - -- void applyModifiers(Multimap modifiers, CraftMetaItem.Applicator tag) { -- if (modifiers == null || modifiers.isEmpty()) { -- if (this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES)) { -- tag.put(CraftMetaItem.ATTRIBUTES, new ItemAttributeModifiers(Collections.emptyList(), false)); -+ @Override -+ public void addItemFlags(ItemFlag... hideFlags) { -+ for (ItemFlag f : hideFlags) { -+ this.hideFlag |= this.getBitModifier(f); - } -- return; - } - -- ItemAttributeModifiers.Builder list = ItemAttributeModifiers.builder(); -- for (Map.Entry entry : modifiers.entries()) { -- if (entry.getKey() == null || entry.getValue() == null) { -- continue; -+ @Override -+ public void removeItemFlags(ItemFlag... hideFlags) { -+ for (ItemFlag f : hideFlags) { -+ this.hideFlag &= ~this.getBitModifier(f); - } -- net.minecraft.world.entity.ai.attributes.AttributeModifier nmsModifier = CraftAttributeInstance.convert(entry.getValue()); -+ } -+ -+ @Override -+ public Set getItemFlags() { -+ Set currentFlags = EnumSet.noneOf(ItemFlag.class); - -- Holder name = CraftAttribute.bukkitToMinecraftHolder(entry.getKey()); -- if (name == null) { -- continue; -+ for (ItemFlag f : ItemFlag.values()) { -+ if (this.hasItemFlag(f)) { -+ currentFlags.add(f); -+ } - } - -- EquipmentSlotGroup group = CraftEquipmentSlot.getNMSGroup(entry.getValue().getSlotGroup()); -- list.add(name, nmsModifier, group); -+ return currentFlags; - } -- tag.put(CraftMetaItem.ATTRIBUTES, list.build().withTooltip(!this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES))); -- } - -- boolean applicableTo(Material type) { -- if (type == Material.AIR || !type.isItem()) { -- return false; -+ @Override -+ public boolean hasItemFlag(ItemFlag flag) { -+ int bitModifier = this.getBitModifier(flag); -+ return (this.hideFlag & bitModifier) == bitModifier; - } - -- if (this.getClass() == CraftMetaItem.class) { -- return true; -+ private int getBitModifier(ItemFlag hideFlag) { -+ return 1 << hideFlag.ordinal(); - } - -- // We assume that the corresponding bukkit interface is always the first one -- return type.asItemType().getItemMetaClass() == this.getClass().getInterfaces()[0]; -- } -+ @Override -+ public List getLore() { -+ return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromComponent)); -+ } - -- @Overridden -- boolean isEmpty() { -- return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper -- } -+ // Paper start -+ @Override -+ public List getLoreComponents() { -+ return this.lore == null ? null : new ArrayList<>(this.lore.stream().map(entry -> -+ net.md_5.bungee.chat.ComponentSerializer.parse(CraftChatMessage.toJSON(entry)) -+ ).collect(java.util.stream.Collectors.toList())); -+ } -+ // Paper end -+ @Override -+ public void setLore(List lore) { -+ if (lore == null || lore.isEmpty()) { -+ this.lore = null; -+ } else { -+ if (this.lore == null) { -+ this.lore = new ArrayList(lore.size()); -+ } else { -+ this.lore.clear(); -+ } -+ CraftMetaItem.safelyAdd(lore, this.lore, false); -+ } -+ } - -- // Paper start -- @Override -- public net.kyori.adventure.text.Component displayName() { -- return displayName == null ? null : io.papermc.paper.adventure.PaperAdventure.asAdventure(displayName); -- } -+ // Paper start -+ @Override -+ public void setLoreComponents(List lore) { -+ if (lore == null) { -+ this.lore = null; -+ } else { -+ if (this.lore == null) { -+ safelyAdd(lore, this.lore = new ArrayList<>(lore.size()), false); -+ } else { -+ this.lore.clear(); -+ safelyAdd(lore, this.lore, false); -+ } -+ } -+ } -+ // Paper end -+ @Override -+ public boolean hasCustomModelData() { -+ return this.customModelData != null; -+ } - -- @Override -- public void displayName(final net.kyori.adventure.text.Component displayName) { -- this.displayName = displayName == null ? null : io.papermc.paper.adventure.PaperAdventure.asVanilla(displayName); -- } -- // Paper end -+ @Override -+ public int getCustomModelData() { -+ Preconditions.checkState(this.hasCustomModelData(), "We don't have CustomModelData! Check hasCustomModelData first!"); -+ return this.customModelData; -+ } - -- @Override -- public String getDisplayName() { -- return CraftChatMessage.fromComponent(this.displayName); -- } -+ @Override -+ public void setCustomModelData(Integer data) { -+ this.customModelData = data; -+ } - -- // Paper start -- @Override -- public net.md_5.bungee.api.chat.BaseComponent[] getDisplayNameComponent() { -- return displayName == null ? new net.md_5.bungee.api.chat.BaseComponent[0] : net.md_5.bungee.chat.ComponentSerializer.parse(CraftChatMessage.toJSON(displayName)); -- } -- // Paper end -- @Override -- public final void setDisplayName(String name) { -- this.displayName = CraftChatMessage.fromStringOrNull(name); -- } -+ @Override -+ public boolean hasBlockData() { -+ return this.blockData != null; -+ } - -- // Paper start -- @Override -- public void setDisplayNameComponent(net.md_5.bungee.api.chat.BaseComponent[] component) { -- this.displayName = CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(component)); -- } -- // Paper end -- @Override -- public boolean hasDisplayName() { -- return this.displayName != null; -- } -+ @Override -+ public BlockData getBlockData(Material material) { -+ BlockState defaultData = CraftBlockType.bukkitToMinecraft(material).defaultBlockState(); -+ return CraftBlockData.fromData((this.hasBlockData()) ? new BlockItemStateProperties(this.blockData).apply(defaultData) : defaultData); -+ } - -- @Override -- public String getItemName() { -- return CraftChatMessage.fromComponent(this.itemName); -- } -+ @Override -+ public void setBlockData(BlockData blockData) { -+ this.blockData = (blockData == null) ? null : ((CraftBlockData) blockData).toStates(); -+ } - -- @Override -- public final void setItemName(String name) { -- this.itemName = CraftChatMessage.fromStringOrNull(name); -- } -+ @Override -+ public int getRepairCost() { -+ return this.repairCost; -+ } - -- @Override -- public boolean hasItemName() { -- return this.itemName != null; -- } -+ @Override -+ public void setRepairCost(int cost) { // TODO: Does this have limits? -+ this.repairCost = cost; -+ } - -- // Paper start - Adventure -- @Override -- public net.kyori.adventure.text.Component itemName() { -- return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.itemName); -- } -+ @Override -+ public boolean isHideTooltip() { -+ return this.hideTooltip; -+ } - -- @Override -- public void itemName(final net.kyori.adventure.text.Component name) { -- this.itemName = io.papermc.paper.adventure.PaperAdventure.asVanilla(name); -- } -- // Paper end - Adventure -+ @Override -+ public void setHideTooltip(boolean hideTooltip) { -+ this.hideTooltip = hideTooltip; -+ } - -- @Override -- public String getLocalizedName() { -- return this.getDisplayName(); -- } -+ @Override -+ public boolean isUnbreakable() { -+ return this.unbreakable; -+ } - -- @Override -- public void setLocalizedName(String name) { -- } -+ @Override -+ public void setUnbreakable(boolean unbreakable) { -+ this.unbreakable = unbreakable; -+ } - -- @Override -- public boolean hasLocalizedName() { -- return false; -- } -+ @Override -+ public boolean hasEnchantmentGlintOverride() { -+ return this.enchantmentGlintOverride != null; -+ } - -- @Override -- public boolean hasLore() { -- return this.lore != null && !this.lore.isEmpty(); -- } -+ @Override -+ public Boolean getEnchantmentGlintOverride() { -+ Preconditions.checkState(this.hasEnchantmentGlintOverride(), "We don't have enchantment_glint_override! Check hasEnchantmentGlintOverride first!"); -+ return this.enchantmentGlintOverride; -+ } - -- // Paper start -- @Override -- public List lore() { -- return this.lore != null ? io.papermc.paper.adventure.PaperAdventure.asAdventure(this.lore) : null; -- } -+ @Override -+ public void setEnchantmentGlintOverride(Boolean override) { -+ this.enchantmentGlintOverride = override; -+ } - -- @Override -- public void lore(final List lore) { -- this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(lore) : null; -- } -- // Paper end -+ @Override -+ public boolean isFireResistant() { -+ return this.fireResistant; -+ } - -- @Override -- public boolean hasRepairCost() { -- return this.repairCost > 0; -- } -+ @Override -+ public void setFireResistant(boolean fireResistant) { -+ this.fireResistant = fireResistant; -+ } - -- @Override -- public boolean hasEnchant(Enchantment ench) { -- Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); -- return this.hasEnchants() && this.enchantments.containsKey(ench); -- } -+ @Override -+ public boolean hasMaxStackSize() { -+ return this.maxStackSize != null; -+ } - -- @Override -- public int getEnchantLevel(Enchantment ench) { -- Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); -- Integer level = this.hasEnchants() ? this.enchantments.get(ench) : null; -- if (level == null) { -- return 0; -+ @Override -+ public int getMaxStackSize() { -+ Preconditions.checkState(this.hasMaxStackSize(), "We don't have max_stack_size! Check hasMaxStackSize first!"); -+ return this.maxStackSize; - } -- return level; -- } - -- @Override -- public Map getEnchants() { -- return this.hasEnchants() ? ImmutableSortedMap.copyOfSorted(this.enchantments) : ImmutableMap.of(); // Paper -- } -+ @Override -+ public void setMaxStackSize(Integer max) { -+ Preconditions.checkArgument(max == null || max > 0, "max_stack_size must be > 0"); -+ Preconditions.checkArgument(max == null || max <= net.minecraft.world.item.Item.ABSOLUTE_MAX_STACK_SIZE, "max_stack_size must be <= 99"); -+ this.maxStackSize = max; -+ } - -- @Override -- public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) { -- Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); -- if (this.enchantments == null) { -- this.enchantments = new EnchantmentMap(); // Paper -+ @Override -+ public boolean hasRarity() { -+ return this.rarity != null; - } - -- if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) { -- Integer old = this.enchantments.put(ench, level); -- return old == null || old != level; -+ @Override -+ public ItemRarity getRarity() { -+ Preconditions.checkState(this.hasRarity(), "We don't have rarity! Check hasRarity first!"); -+ return this.rarity; - } -- return false; -- } - -- @Override -- public boolean removeEnchant(Enchantment ench) { -- Preconditions.checkArgument(ench != null, "Enchantment cannot be null"); -- boolean enchantmentRemoved = this.hasEnchants() && this.enchantments.remove(ench) != null; -- // If we no longer have any enchantments, then clear enchantment tag -- if (enchantmentRemoved && this.enchantments.isEmpty()) { -- this.enchantments = null; -+ @Override -+ public void setRarity(ItemRarity rarity) { -+ this.rarity = rarity; - } -- return enchantmentRemoved; -- } - -- @Override -- public void removeEnchantments() { -- if (this.hasEnchants()) { -- this.enchantments.clear(); -+ @Override -+ public boolean hasFood() { -+ return this.food != null; - } -- } - -- @Override -- public boolean hasEnchants() { -- return !(this.enchantments == null || this.enchantments.isEmpty()); -- } -+ @Override -+ public FoodComponent getFood() { -+ return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, 0, Optional.empty(), Collections.emptyList())); -+ } - -- @Override -- public boolean hasConflictingEnchant(Enchantment ench) { -- return CraftMetaItem.checkConflictingEnchants(this.enchantments, ench); -- } -+ @Override -+ public void setFood(FoodComponent food) { -+ this.food = (food == null) ? null : new CraftFoodComponent((CraftFoodComponent) food); -+ } - -- @Override -- public void addItemFlags(ItemFlag... hideFlags) { -- for (ItemFlag f : hideFlags) { -- this.hideFlag |= this.getBitModifier(f); -+ @Override -+ public boolean hasTool() { -+ return this.tool != null; - } -- } - -- @Override -- public void removeItemFlags(ItemFlag... hideFlags) { -- for (ItemFlag f : hideFlags) { -- this.hideFlag &= ~this.getBitModifier(f); -+ @Override -+ public ToolComponent getTool() { -+ return (this.hasTool()) ? new CraftToolComponent(this.tool) : new CraftToolComponent(new Tool(Collections.emptyList(), 1.0F, 0)); - } -- } - -- @Override -- public Set getItemFlags() { -- Set currentFlags = EnumSet.noneOf(ItemFlag.class); -+ @Override -+ public void setTool(ToolComponent tool) { -+ this.tool = (tool == null) ? null : new CraftToolComponent((CraftToolComponent) tool); -+ } - -- for (ItemFlag f : ItemFlag.values()) { -- if (this.hasItemFlag(f)) { -- currentFlags.add(f); -- } -+ @Override -+ public boolean hasJukeboxPlayable() { -+ return this.jukebox != null; - } - -- return currentFlags; -- } -+ @Override -+ public JukeboxPlayableComponent getJukeboxPlayable() { -+ return (this.hasJukeboxPlayable()) ? new CraftJukeboxComponent(this.jukebox) : new CraftJukeboxComponent(new JukeboxPlayable(new EitherHolder<>(JukeboxSongs.THIRTEEN), true)); -+ } - -- @Override -- public boolean hasItemFlag(ItemFlag flag) { -- int bitModifier = this.getBitModifier(flag); -- return (this.hideFlag & bitModifier) == bitModifier; -- } -+ @Override -+ public void setJukeboxPlayable(JukeboxPlayableComponent jukeboxPlayable) { -+ this.jukebox = (jukeboxPlayable == null) ? null : new CraftJukeboxComponent((CraftJukeboxComponent) jukeboxPlayable); -+ } - -- private int getBitModifier(ItemFlag hideFlag) { -- return 1 << hideFlag.ordinal(); -- } -+ @Override -+ public boolean hasAttributeModifiers() { -+ return this.attributeModifiers != null && !this.attributeModifiers.isEmpty(); -+ } - -- @Override -- public List getLore() { -- return this.lore == null ? null : new ArrayList(Lists.transform(this.lore, CraftChatMessage::fromComponent)); -- } -+ @Override -+ public Multimap getAttributeModifiers() { -+ return this.hasAttributeModifiers() ? ImmutableMultimap.copyOf(this.attributeModifiers) : null; -+ } - -- // Paper start -- @Override -- public List getLoreComponents() { -- return this.lore == null ? null : new ArrayList<>(this.lore.stream().map(entry -> -- net.md_5.bungee.chat.ComponentSerializer.parse(CraftChatMessage.toJSON(entry)) -- ).collect(java.util.stream.Collectors.toList())); -- } -- // Paper end -- @Override -- public void setLore(List lore) { -- if (lore == null || lore.isEmpty()) { -- this.lore = null; -- } else { -- if (this.lore == null) { -- this.lore = new ArrayList(lore.size()); -- } else { -- this.lore.clear(); -+ private void checkAttributeList() { -+ if (this.attributeModifiers == null) { -+ this.attributeModifiers = LinkedHashMultimap.create(); - } -- CraftMetaItem.safelyAdd(lore, this.lore, false); - } -- } - -- // Paper start -- @Override -- public void setLoreComponents(List lore) { -- if (lore == null) { -- this.lore = null; -- } else { -- if (this.lore == null) { -- safelyAdd(lore, this.lore = new ArrayList<>(lore.size()), false); -- } else { -- this.lore.clear(); -- safelyAdd(lore, this.lore, false); -+ @Override -+ public Multimap getAttributeModifiers(@Nullable EquipmentSlot slot) { -+ this.checkAttributeList(); -+ SetMultimap result = LinkedHashMultimap.create(); -+ for (Map.Entry entry : this.attributeModifiers.entries()) { -+ if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { -+ result.put(entry.getKey(), entry.getValue()); -+ } - } -+ return result; - } -- } -- // Paper end -- @Override -- public boolean hasCustomModelData() { -- return this.customModelData != null; -- } -- -- @Override -- public int getCustomModelData() { -- Preconditions.checkState(this.hasCustomModelData(), "We don't have CustomModelData! Check hasCustomModelData first!"); -- return this.customModelData; -- } -- -- @Override -- public void setCustomModelData(Integer data) { -- this.customModelData = data; -- } -- -- @Override -- public boolean hasBlockData() { -- return this.blockData != null; -- } -- -- @Override -- public BlockData getBlockData(Material material) { -- BlockState defaultData = CraftBlockType.bukkitToMinecraft(material).defaultBlockState(); -- return CraftBlockData.fromData((this.hasBlockData()) ? new BlockItemStateProperties(this.blockData).apply(defaultData) : defaultData); -- } -- -- @Override -- public void setBlockData(BlockData blockData) { -- this.blockData = (blockData == null) ? null : ((CraftBlockData) blockData).toStates(); -- } -- -- @Override -- public int getRepairCost() { -- return this.repairCost; -- } -- -- @Override -- public void setRepairCost(int cost) { // TODO: Does this have limits? -- this.repairCost = cost; -- } -- -- @Override -- public boolean isHideTooltip() { -- return this.hideTooltip; -- } -- -- @Override -- public void setHideTooltip(boolean hideTooltip) { -- this.hideTooltip = hideTooltip; -- } -- -- @Override -- public boolean isUnbreakable() { -- return this.unbreakable; -- } -- -- @Override -- public void setUnbreakable(boolean unbreakable) { -- this.unbreakable = unbreakable; -- } -- -- @Override -- public boolean hasEnchantmentGlintOverride() { -- return this.enchantmentGlintOverride != null; -- } -- -- @Override -- public Boolean getEnchantmentGlintOverride() { -- Preconditions.checkState(this.hasEnchantmentGlintOverride(), "We don't have enchantment_glint_override! Check hasEnchantmentGlintOverride first!"); -- return this.enchantmentGlintOverride; -- } -- -- @Override -- public void setEnchantmentGlintOverride(Boolean override) { -- this.enchantmentGlintOverride = override; -- } - -- @Override -- public boolean isFireResistant() { -- return this.fireResistant; -- } -+ @Override -+ public Collection getAttributeModifiers(@Nonnull Attribute attribute) { -+ Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -+ return this.attributeModifiers.containsKey(attribute) ? ImmutableList.copyOf(this.attributeModifiers.get(attribute)) : null; -+ } - -- @Override -- public void setFireResistant(boolean fireResistant) { -- this.fireResistant = fireResistant; -- } -+ @Override -+ public boolean addAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { -+ Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -+ Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); -+ this.checkAttributeList(); -+ for (Map.Entry entry : this.attributeModifiers.entries()) { -+ Preconditions.checkArgument(!(entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine -+ } -+ return this.attributeModifiers.put(attribute, modifier); -+ } - -- @Override -- public boolean hasMaxStackSize() { -- return this.maxStackSize != null; -- } -+ @Override -+ public void setAttributeModifiers(@Nullable Multimap attributeModifiers) { -+ if (attributeModifiers == null || attributeModifiers.isEmpty()) { -+ this.attributeModifiers = LinkedHashMultimap.create(); -+ return; -+ } - -- @Override -- public int getMaxStackSize() { -- Preconditions.checkState(this.hasMaxStackSize(), "We don't have max_stack_size! Check hasMaxStackSize first!"); -- return this.maxStackSize; -- } -+ this.checkAttributeList(); -+ this.attributeModifiers.clear(); - -- @Override -- public void setMaxStackSize(Integer max) { -- Preconditions.checkArgument(max == null || max > 0, "max_stack_size must be > 0"); -- Preconditions.checkArgument(max == null || max <= net.minecraft.world.item.Item.ABSOLUTE_MAX_STACK_SIZE, "max_stack_size must be <= 99"); -- this.maxStackSize = max; -- } -+ Iterator> iterator = attributeModifiers.entries().iterator(); -+ while (iterator.hasNext()) { -+ Map.Entry next = iterator.next(); - -- @Override -- public boolean hasRarity() { -- return this.rarity != null; -- } -+ if (next.getKey() == null || next.getValue() == null) { -+ iterator.remove(); -+ continue; -+ } -+ this.attributeModifiers.put(next.getKey(), next.getValue()); -+ } -+ } - -- @Override -- public ItemRarity getRarity() { -- Preconditions.checkState(this.hasRarity(), "We don't have rarity! Check hasRarity first!"); -- return this.rarity; -- } -+ @Override -+ public boolean removeAttributeModifier(@Nonnull Attribute attribute) { -+ Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -+ this.checkAttributeList(); -+ return !this.attributeModifiers.removeAll(attribute).isEmpty(); -+ } - -- @Override -- public void setRarity(ItemRarity rarity) { -- this.rarity = rarity; -- } -+ @Override -+ public boolean removeAttributeModifier(@Nullable EquipmentSlot slot) { -+ this.checkAttributeList(); -+ int removed = 0; -+ Iterator> iter = this.attributeModifiers.entries().iterator(); - -- @Override -- public boolean hasFood() { -- return this.food != null; -- } -+ while (iter.hasNext()) { -+ Map.Entry entry = iter.next(); -+ // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a - -+ // set slot are active in any slot. -+ if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { -+ iter.remove(); -+ ++removed; -+ } -+ } -+ return removed > 0; -+ } - -- @Override -- public FoodComponent getFood() { -- return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, 0, Optional.empty(), Collections.emptyList())); -- } -+ @Override -+ public boolean removeAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { -+ Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -+ Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); -+ this.checkAttributeList(); -+ int removed = 0; -+ Iterator> iter = this.attributeModifiers.entries().iterator(); - -- @Override -- public void setFood(FoodComponent food) { -- this.food = (food == null) ? null : new CraftFoodComponent((CraftFoodComponent) food); -- } -+ while (iter.hasNext()) { -+ Map.Entry entry = iter.next(); -+ if (entry.getKey() == null || entry.getValue() == null) { -+ iter.remove(); -+ ++removed; -+ continue; // remove all null values while we are here -+ } - -- @Override -- public boolean hasTool() { -- return this.tool != null; -- } -+ if (entry.getKey() == attribute && entry.getValue().getKey().equals(modifier.getKey())) { -+ iter.remove(); -+ ++removed; -+ } -+ } -+ return removed > 0; -+ } - -- @Override -- public ToolComponent getTool() { -- return (this.hasTool()) ? new CraftToolComponent(this.tool) : new CraftToolComponent(new Tool(Collections.emptyList(), 1.0F, 0)); -- } -+ @Override -+ public String getAsString() { -+ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); -+ this.applyToItem(tag); -+ DataComponentPatch patch = tag.build(); -+ Tag nbt = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), patch).getOrThrow(); -+ return nbt.toString(); -+ } - -- @Override -- public void setTool(ToolComponent tool) { -- this.tool = (tool == null) ? null : new CraftToolComponent((CraftToolComponent) tool); -- } -+ @Override -+ public String getAsComponentString() { -+ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); -+ this.applyToItem(tag); -+ DataComponentPatch patch = tag.build(); - -- @Override -- public boolean hasJukeboxPlayable() { -- return this.jukebox != null; -- } -+ RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); -+ DynamicOps ops = registryAccess.createSerializationContext(NbtOps.INSTANCE); -+ Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); - -- @Override -- public JukeboxPlayableComponent getJukeboxPlayable() { -- return (this.hasJukeboxPlayable()) ? new CraftJukeboxComponent(this.jukebox) : new CraftJukeboxComponent(new JukeboxPlayable(new EitherHolder<>(JukeboxSongs.THIRTEEN), true)); -- } -+ StringJoiner componentString = new StringJoiner(",", "[", "]"); -+ for (Entry, Optional> entry : patch.entrySet()) { -+ DataComponentType componentType = entry.getKey(); -+ Optional componentValue = entry.getValue(); -+ String componentKey = componentTypeRegistry.getResourceKey(componentType).orElseThrow().location().toString(); - -- @Override -- public void setJukeboxPlayable(JukeboxPlayableComponent jukeboxPlayable) { -- this.jukebox = (jukeboxPlayable == null) ? null : new CraftJukeboxComponent((CraftJukeboxComponent) jukeboxPlayable); -- } -+ if (componentValue.isPresent()) { -+ Tag componentValueAsNBT = (Tag) ((DataComponentType) componentType).codecOrThrow().encodeStart(ops, componentValue.get()).getOrThrow(); -+ String componentValueAsNBTString = new SnbtPrinterTagVisitor("", 0, new ArrayList<>()).visit(componentValueAsNBT); -+ componentString.add(componentKey + "=" + componentValueAsNBTString); -+ } else { -+ componentString.add("!" + componentKey); -+ } -+ } - -- @Override -- public boolean hasAttributeModifiers() { -- return this.attributeModifiers != null && !this.attributeModifiers.isEmpty(); -- } -+ return componentString.toString(); -+ } - -- @Override -- public Multimap getAttributeModifiers() { -- return this.hasAttributeModifiers() ? ImmutableMultimap.copyOf(this.attributeModifiers) : null; -- } -+ @Override -+ public CustomItemTagContainer getCustomTagContainer() { -+ return new DeprecatedCustomTagContainer(this.getPersistentDataContainer()); -+ } - -- private void checkAttributeList() { -- if (this.attributeModifiers == null) { -- this.attributeModifiers = LinkedHashMultimap.create(); -+ @Override -+ public PersistentDataContainer getPersistentDataContainer() { -+ return this.persistentDataContainer; - } -- } - -- @Override -- public Multimap getAttributeModifiers(@Nullable EquipmentSlot slot) { -- this.checkAttributeList(); -- SetMultimap result = LinkedHashMultimap.create(); -- for (Map.Entry entry : this.attributeModifiers.entries()) { -- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { -- result.put(entry.getKey(), entry.getValue()); -+ private static boolean compareModifiers(Multimap first, Multimap second) { -+ if (first == null || second == null) { -+ return false; -+ } -+ for (Map.Entry entry : first.entries()) { -+ if (!second.containsEntry(entry.getKey(), entry.getValue())) { -+ return false; -+ } - } -+ for (Map.Entry entry : second.entries()) { -+ if (!first.containsEntry(entry.getKey(), entry.getValue())) { -+ return false; -+ } -+ } -+ return true; - } -- return result; -- } -- -- @Override -- public Collection getAttributeModifiers(@Nonnull Attribute attribute) { -- Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -- return this.attributeModifiers.containsKey(attribute) ? ImmutableList.copyOf(this.attributeModifiers.get(attribute)) : null; -- } - -- @Override -- public boolean addAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { -- Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -- Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); -- this.checkAttributeList(); -- for (Map.Entry entry : this.attributeModifiers.entries()) { -- Preconditions.checkArgument(!(entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine -+ @Override -+ public boolean hasDamage() { -+ return this.damage > 0; - } -- return this.attributeModifiers.put(attribute, modifier); -- } - -- @Override -- public void setAttributeModifiers(@Nullable Multimap attributeModifiers) { -- if (attributeModifiers == null || attributeModifiers.isEmpty()) { -- this.attributeModifiers = LinkedHashMultimap.create(); -- return; -+ @Override -+ public int getDamage() { -+ return this.damage; - } - -- this.checkAttributeList(); -- this.attributeModifiers.clear(); -- -- Iterator> iterator = attributeModifiers.entries().iterator(); -- while (iterator.hasNext()) { -- Map.Entry next = iterator.next(); -+ @Override -+ public void setDamage(int damage) { -+ this.damage = damage; -+ } - -- if (next.getKey() == null || next.getValue() == null) { -- iterator.remove(); -- continue; -- } -- this.attributeModifiers.put(next.getKey(), next.getValue()); -+ @Override -+ public boolean hasMaxDamage() { -+ return this.maxDamage != null; - } -- } - -- @Override -- public boolean removeAttributeModifier(@Nonnull Attribute attribute) { -- Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -- this.checkAttributeList(); -- return !this.attributeModifiers.removeAll(attribute).isEmpty(); -- } -+ @Override -+ public int getMaxDamage() { -+ Preconditions.checkState(this.hasMaxDamage(), "We don't have max_damage! Check hasMaxDamage first!"); -+ return this.maxDamage; -+ } - -- @Override -- public boolean removeAttributeModifier(@Nullable EquipmentSlot slot) { -- this.checkAttributeList(); -- int removed = 0; -- Iterator> iter = this.attributeModifiers.entries().iterator(); -+ @Override -+ public void setMaxDamage(Integer maxDamage) { -+ this.maxDamage = maxDamage; -+ } - -- while (iter.hasNext()) { -- Map.Entry entry = iter.next(); -- // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a - -- // set slot are active in any slot. -- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { -- iter.remove(); -- ++removed; -+ @Override -+ public final boolean equals(Object object) { -+ if (object == null) { -+ return false; - } -+ if (object == this) { -+ return true; -+ } -+ if (!(object instanceof CraftMetaItem)) { -+ return false; -+ } -+ return CraftItemFactory.instance().equals(this, (ItemMeta) object); -+ } -+ -+ /** -+ * This method is almost as weird as notUncommon. -+ * Only return false if your common internals are unequal. -+ * Checking your own internals is redundant if you are not common, as notUncommon is meant for checking those 'not common' variables. -+ */ -+ @Overridden -+ boolean equalsCommon(CraftMetaItem that) { -+ return ((this.hasDisplayName() ? that.hasDisplayName() && this.displayName.equals(that.displayName) : !that.hasDisplayName())) -+ && (this.hasItemName() ? that.hasItemName() && this.itemName.equals(that.itemName) : !that.hasItemName()) -+ && (this.hasEnchants() ? that.hasEnchants() && this.enchantments.equals(that.enchantments) : !that.hasEnchants()) -+ && (Objects.equals(this.lore, that.lore)) -+ && (this.hasCustomModelData() ? that.hasCustomModelData() && this.customModelData.equals(that.customModelData) : !that.hasCustomModelData()) -+ && (this.hasBlockData() ? that.hasBlockData() && this.blockData.equals(that.blockData) : !that.hasBlockData()) -+ && (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost()) -+ && (this.hasAttributeModifiers() ? that.hasAttributeModifiers() && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : !that.hasAttributeModifiers()) -+ && (this.unhandledTags.equals(that.unhandledTags)) -+ && (this.removedTags.equals(that.removedTags)) -+ && (Objects.equals(this.customTag, that.customTag)) -+ && (this.persistentDataContainer.equals(that.persistentDataContainer)) -+ && (this.hideFlag == that.hideFlag) -+ && (this.isHideTooltip() == that.isHideTooltip()) -+ && (this.isUnbreakable() == that.isUnbreakable()) -+ && (this.hasEnchantmentGlintOverride() ? that.hasEnchantmentGlintOverride() && this.enchantmentGlintOverride.equals(that.enchantmentGlintOverride) : !that.hasEnchantmentGlintOverride()) -+ && (this.fireResistant == that.fireResistant) -+ && (this.hasMaxStackSize() ? that.hasMaxStackSize() && this.maxStackSize.equals(that.maxStackSize) : !that.hasMaxStackSize()) -+ && (this.rarity == that.rarity) -+ && (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood()) -+ && (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool()) -+ && (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable()) -+ && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) -+ && (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage()) -+ && (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper -+ && (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper -+ && (this.version == that.version); -+ } -+ -+ /** -+ * This method is a bit weird... -+ * Return true if you are a common class OR your uncommon parts are empty. -+ * Empty uncommon parts implies the NBT data would be equivalent if both were applied to an item -+ */ -+ @Overridden -+ boolean notUncommon(CraftMetaItem meta) { -+ return true; - } -- return removed > 0; -- } - -- @Override -- public boolean removeAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { -- Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -- Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); -- this.checkAttributeList(); -- int removed = 0; -- Iterator> iter = this.attributeModifiers.entries().iterator(); -- -- while (iter.hasNext()) { -- Map.Entry entry = iter.next(); -- if (entry.getKey() == null || entry.getValue() == null) { -- iter.remove(); -- ++removed; -- continue; // remove all null values while we are here -+ @Override -+ public final int hashCode() { -+ return this.applyHash(); -+ } -+ -+ @Overridden -+ int applyHash() { -+ int hash = 3; -+ hash = 61 * hash + (this.hasDisplayName() ? this.displayName.hashCode() : 0); -+ hash = 61 * hash + (this.hasItemName() ? this.itemName.hashCode() : 0); -+ hash = 61 * hash + ((this.lore != null) ? this.lore.hashCode() : 0); -+ hash = 61 * hash + (this.hasCustomModelData() ? this.customModelData.hashCode() : 0); -+ hash = 61 * hash + (this.hasBlockData() ? this.blockData.hashCode() : 0); -+ hash = 61 * hash + (this.hasEnchants() ? this.enchantments.hashCode() : 0); -+ hash = 61 * hash + (this.hasRepairCost() ? this.repairCost : 0); -+ hash = 61 * hash + this.unhandledTags.hashCode(); -+ hash = 61 * hash + this.removedTags.hashCode(); -+ hash = 61 * hash + ((this.customTag != null) ? this.customTag.hashCode() : 0); -+ hash = 61 * hash + (!this.persistentDataContainer.isEmpty() ? this.persistentDataContainer.hashCode() : 0); -+ hash = 61 * hash + this.hideFlag; -+ hash = 61 * hash + (this.isHideTooltip() ? 1231 : 1237); -+ hash = 61 * hash + (this.isUnbreakable() ? 1231 : 1237); -+ hash = 61 * hash + (this.hasEnchantmentGlintOverride() ? this.enchantmentGlintOverride.hashCode() : 0); -+ hash = 61 * hash + (this.isFireResistant() ? 1231 : 1237); -+ hash = 61 * hash + (this.hasMaxStackSize() ? this.maxStackSize.hashCode() : 0); -+ hash = 61 * hash + (this.hasRarity() ? this.rarity.hashCode() : 0); -+ hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0); -+ hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0); -+ hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0); -+ hash = 61 * hash + (this.hasDamage() ? this.damage : 0); -+ hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237); -+ hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); -+ hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper -+ hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper -+ hash = 61 * hash + this.version; -+ return hash; -+ } -+ -+ @Overridden -+ @Override -+ public CraftMetaItem clone() { -+ try { -+ CraftMetaItem clone = (CraftMetaItem) super.clone(); -+ if (this.lore != null) { -+ clone.lore = new ArrayList(this.lore); -+ } -+ clone.customModelData = this.customModelData; -+ clone.blockData = this.blockData; -+ if (this.enchantments != null) { -+ clone.enchantments = new EnchantmentMap(this.enchantments); // Paper -+ } -+ if (this.hasAttributeModifiers()) { -+ clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); -+ } -+ if (this.customTag != null) { -+ clone.customTag = this.customTag.copy(); -+ } -+ clone.removedTags = Sets.newHashSet(this.removedTags); -+ clone.persistentDataContainer = new CraftPersistentDataContainer(this.persistentDataContainer.getTagsCloned(), CraftMetaItem.DATA_TYPE_REGISTRY); // Paper - deep clone NBT tags -+ clone.hideFlag = this.hideFlag; -+ clone.hideTooltip = this.hideTooltip; -+ clone.unbreakable = this.unbreakable; -+ clone.enchantmentGlintOverride = this.enchantmentGlintOverride; -+ clone.fireResistant = this.fireResistant; -+ clone.maxStackSize = this.maxStackSize; -+ clone.rarity = this.rarity; -+ if (this.hasFood()) { -+ clone.food = new CraftFoodComponent(this.food); -+ } -+ if (this.hasTool()) { -+ clone.tool = new CraftToolComponent(this.tool); -+ } -+ if (this.hasJukeboxPlayable()) { -+ clone.jukebox = new CraftJukeboxComponent(this.jukebox); -+ } -+ clone.damage = this.damage; -+ clone.maxDamage = this.maxDamage; -+ clone.version = this.version; -+ // Paper start -+ if (this.canPlaceOnPredicates != null) { -+ clone.canPlaceOnPredicates = List.copyOf(this.canPlaceOnPredicates); -+ } -+ if (this.canBreakPredicates != null) { -+ clone.canBreakPredicates = List.copyOf(this.canBreakPredicates); -+ } -+ // Paper end -+ return clone; -+ } catch (CloneNotSupportedException e) { -+ throw new Error(e); - } -+ } - -- if (entry.getKey() == attribute && entry.getValue().getKey().equals(modifier.getKey())) { -- iter.remove(); -- ++removed; -- } -+ @Override -+ public final Map serialize() { -+ ImmutableMap.Builder map = ImmutableMap.builder(); -+ map.put(SerializableMeta.TYPE_FIELD, SerializableMeta.classMap.get(this.getClass())); -+ this.serialize(map); -+ return map.build(); - } -- return removed > 0; -- } - -- @Override -- public String getAsString() { -- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); -- this.applyToItem(tag); -- DataComponentPatch patch = tag.build(); -- Tag nbt = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), patch).getOrThrow(); -- return nbt.toString(); -- } -+ @Overridden -+ ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { -+ if (this.hasDisplayName()) { -+ builder.put(CraftMetaItem.NAME.BUKKIT, CraftChatMessage.toJSON(this.displayName)); -+ } - -- @Override -- public String getAsComponentString() { -- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); -- this.applyToItem(tag); -- DataComponentPatch patch = tag.build(); -- -- RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); -- DynamicOps ops = registryAccess.createSerializationContext(NbtOps.INSTANCE); -- Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); -- -- StringJoiner componentString = new StringJoiner(",", "[", "]"); -- for (Entry, Optional> entry : patch.entrySet()) { -- DataComponentType componentType = entry.getKey(); -- Optional componentValue = entry.getValue(); -- String componentKey = componentTypeRegistry.getResourceKey(componentType).orElseThrow().location().toString(); -- -- if (componentValue.isPresent()) { -- Tag componentValueAsNBT = (Tag) ((DataComponentType) componentType).codecOrThrow().encodeStart(ops, componentValue.get()).getOrThrow(); -- String componentValueAsNBTString = new SnbtPrinterTagVisitor("", 0, new ArrayList<>()).visit(componentValueAsNBT); -- componentString.add(componentKey + "=" + componentValueAsNBTString); -- } else { -- componentString.add("!" + componentKey); -+ if (this.hasItemName()) { -+ builder.put(CraftMetaItem.ITEM_NAME.BUKKIT, CraftChatMessage.toJSON(this.itemName)); - } -- } - -- return componentString.toString(); -- } -+ if (this.hasLore()) { -+ // SPIGOT-7625: Convert lore to json before serializing it -+ List jsonLore = new ArrayList<>(); - -- @Override -- public CustomItemTagContainer getCustomTagContainer() { -- return new DeprecatedCustomTagContainer(this.getPersistentDataContainer()); -- } -+ for (Component component : this.lore) { -+ jsonLore.add(CraftChatMessage.toJSON(component)); -+ } - -- @Override -- public PersistentDataContainer getPersistentDataContainer() { -- return this.persistentDataContainer; -- } -+ builder.put(CraftMetaItem.LORE.BUKKIT, jsonLore); -+ } - -- private static boolean compareModifiers(Multimap first, Multimap second) { -- if (first == null || second == null) { -- return false; -- } -- for (Map.Entry entry : first.entries()) { -- if (!second.containsEntry(entry.getKey(), entry.getValue())) { -- return false; -+ if (this.hasCustomModelData()) { -+ builder.put(CraftMetaItem.CUSTOM_MODEL_DATA.BUKKIT, this.customModelData); - } -- } -- for (Map.Entry entry : second.entries()) { -- if (!first.containsEntry(entry.getKey(), entry.getValue())) { -- return false; -+ if (this.hasBlockData()) { -+ builder.put(CraftMetaItem.BLOCK_DATA.BUKKIT, this.blockData); - } -- } -- return true; -- } - -- @Override -- public boolean hasDamage() { -- return this.damage > 0; -- } -+ CraftMetaItem.serializeEnchantments(this.enchantments, builder, CraftMetaItem.ENCHANTMENTS); -+ CraftMetaItem.serializeModifiers(this.attributeModifiers, builder, CraftMetaItem.ATTRIBUTES); - -- @Override -- public int getDamage() { -- return this.damage; -- } -+ if (this.hasRepairCost()) { -+ builder.put(CraftMetaItem.REPAIR.BUKKIT, this.repairCost); -+ } - -- @Override -- public void setDamage(int damage) { -- this.damage = damage; -- } -+ List hideFlags = new ArrayList(); -+ for (ItemFlag hideFlagEnum : this.getItemFlags()) { -+ hideFlags.add(CraftItemFlag.bukkitToString(hideFlagEnum)); -+ } -+ if (!hideFlags.isEmpty()) { -+ builder.put(CraftMetaItem.HIDEFLAGS.BUKKIT, hideFlags); -+ } - -- @Override -- public boolean hasMaxDamage() { -- return this.maxDamage != null; -- } -+ if (this.isHideTooltip()) { -+ builder.put(CraftMetaItem.HIDE_TOOLTIP.BUKKIT, this.hideTooltip); -+ } - -- @Override -- public int getMaxDamage() { -- Preconditions.checkState(this.hasMaxDamage(), "We don't have max_damage! Check hasMaxDamage first!"); -- return this.maxDamage; -- } -+ if (this.isUnbreakable()) { -+ builder.put(CraftMetaItem.UNBREAKABLE.BUKKIT, this.unbreakable); -+ } - -- @Override -- public void setMaxDamage(Integer maxDamage) { -- this.maxDamage = maxDamage; -- } -+ if (this.hasEnchantmentGlintOverride()) { -+ builder.put(CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.BUKKIT, this.enchantmentGlintOverride); -+ } - -- @Override -- public final boolean equals(Object object) { -- if (object == null) { -- return false; -- } -- if (object == this) { -- return true; -- } -- if (!(object instanceof CraftMetaItem)) { -- return false; -- } -- return CraftItemFactory.instance().equals(this, (ItemMeta) object); -- } -+ if (this.isFireResistant()) { -+ builder.put(CraftMetaItem.FIRE_RESISTANT.BUKKIT, this.fireResistant); -+ } - -- /** -- * This method is almost as weird as notUncommon. -- * Only return false if your common internals are unequal. -- * Checking your own internals is redundant if you are not common, as notUncommon is meant for checking those 'not common' variables. -- */ -- @Overridden -- boolean equalsCommon(CraftMetaItem that) { -- return ((this.hasDisplayName() ? that.hasDisplayName() && this.displayName.equals(that.displayName) : !that.hasDisplayName())) -- && (this.hasItemName() ? that.hasItemName() && this.itemName.equals(that.itemName) : !that.hasItemName()) -- && (this.hasEnchants() ? that.hasEnchants() && this.enchantments.equals(that.enchantments) : !that.hasEnchants()) -- && (Objects.equals(this.lore, that.lore)) -- && (this.hasCustomModelData() ? that.hasCustomModelData() && this.customModelData.equals(that.customModelData) : !that.hasCustomModelData()) -- && (this.hasBlockData() ? that.hasBlockData() && this.blockData.equals(that.blockData) : !that.hasBlockData()) -- && (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost()) -- && (this.hasAttributeModifiers() ? that.hasAttributeModifiers() && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : !that.hasAttributeModifiers()) -- && (this.unhandledTags.equals(that.unhandledTags)) -- && (this.removedTags.equals(that.removedTags)) -- && (Objects.equals(this.customTag, that.customTag)) -- && (this.persistentDataContainer.equals(that.persistentDataContainer)) -- && (this.hideFlag == that.hideFlag) -- && (this.isHideTooltip() == that.isHideTooltip()) -- && (this.isUnbreakable() == that.isUnbreakable()) -- && (this.hasEnchantmentGlintOverride() ? that.hasEnchantmentGlintOverride() && this.enchantmentGlintOverride.equals(that.enchantmentGlintOverride) : !that.hasEnchantmentGlintOverride()) -- && (this.fireResistant == that.fireResistant) -- && (this.hasMaxStackSize() ? that.hasMaxStackSize() && this.maxStackSize.equals(that.maxStackSize) : !that.hasMaxStackSize()) -- && (this.rarity == that.rarity) -- && (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood()) -- && (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool()) -- && (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable()) -- && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) -- && (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage()) -- && (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper -- && (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper -- && (this.version == that.version); -- } -+ if (this.hasMaxStackSize()) { -+ builder.put(CraftMetaItem.MAX_STACK_SIZE.BUKKIT, this.maxStackSize); -+ } - -- /** -- * This method is a bit weird... -- * Return true if you are a common class OR your uncommon parts are empty. -- * Empty uncommon parts implies the NBT data would be equivalent if both were applied to an item -- */ -- @Overridden -- boolean notUncommon(CraftMetaItem meta) { -- return true; -- } -+ if (this.hasRarity()) { -+ builder.put(CraftMetaItem.RARITY.BUKKIT, this.rarity.name()); -+ } - -- @Override -- public final int hashCode() { -- return this.applyHash(); -- } -+ if (this.hasFood()) { -+ builder.put(CraftMetaItem.FOOD.BUKKIT, this.food); -+ } - -- @Overridden -- int applyHash() { -- int hash = 3; -- hash = 61 * hash + (this.hasDisplayName() ? this.displayName.hashCode() : 0); -- hash = 61 * hash + (this.hasItemName() ? this.itemName.hashCode() : 0); -- hash = 61 * hash + ((this.lore != null) ? this.lore.hashCode() : 0); -- hash = 61 * hash + (this.hasCustomModelData() ? this.customModelData.hashCode() : 0); -- hash = 61 * hash + (this.hasBlockData() ? this.blockData.hashCode() : 0); -- hash = 61 * hash + (this.hasEnchants() ? this.enchantments.hashCode() : 0); -- hash = 61 * hash + (this.hasRepairCost() ? this.repairCost : 0); -- hash = 61 * hash + this.unhandledTags.hashCode(); -- hash = 61 * hash + this.removedTags.hashCode(); -- hash = 61 * hash + ((this.customTag != null) ? this.customTag.hashCode() : 0); -- hash = 61 * hash + (!this.persistentDataContainer.isEmpty() ? this.persistentDataContainer.hashCode() : 0); -- hash = 61 * hash + this.hideFlag; -- hash = 61 * hash + (this.isHideTooltip() ? 1231 : 1237); -- hash = 61 * hash + (this.isUnbreakable() ? 1231 : 1237); -- hash = 61 * hash + (this.hasEnchantmentGlintOverride() ? this.enchantmentGlintOverride.hashCode() : 0); -- hash = 61 * hash + (this.isFireResistant() ? 1231 : 1237); -- hash = 61 * hash + (this.hasMaxStackSize() ? this.maxStackSize.hashCode() : 0); -- hash = 61 * hash + (this.hasRarity() ? this.rarity.hashCode() : 0); -- hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0); -- hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0); -- hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0); -- hash = 61 * hash + (this.hasDamage() ? this.damage : 0); -- hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237); -- hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); -- hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper -- hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper -- hash = 61 * hash + this.version; -- return hash; -- } -+ if (this.hasTool()) { -+ builder.put(CraftMetaItem.TOOL.BUKKIT, this.tool); -+ } - -- @Overridden -- @Override -- public CraftMetaItem clone() { -- try { -- CraftMetaItem clone = (CraftMetaItem) super.clone(); -- if (this.lore != null) { -- clone.lore = new ArrayList(this.lore); -+ if (this.hasJukeboxPlayable()) { -+ builder.put(CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, this.jukebox); - } -- clone.customModelData = this.customModelData; -- clone.blockData = this.blockData; -- if (this.enchantments != null) { -- clone.enchantments = new EnchantmentMap(this.enchantments); // Paper -+ -+ if (this.hasDamage()) { -+ builder.put(CraftMetaItem.DAMAGE.BUKKIT, this.damage); - } -- if (this.hasAttributeModifiers()) { -- clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); -+ -+ if (this.hasMaxDamage()) { -+ builder.put(CraftMetaItem.MAX_DAMAGE.BUKKIT, this.maxDamage); - } -- if (this.customTag != null) { -- clone.customTag = this.customTag.copy(); -- } -- clone.removedTags = Sets.newHashSet(this.removedTags); -- clone.persistentDataContainer = new CraftPersistentDataContainer(this.persistentDataContainer.getTagsCloned(), CraftMetaItem.DATA_TYPE_REGISTRY); // Paper - deep clone NBT tags -- clone.hideFlag = this.hideFlag; -- clone.hideTooltip = this.hideTooltip; -- clone.unbreakable = this.unbreakable; -- clone.enchantmentGlintOverride = this.enchantmentGlintOverride; -- clone.fireResistant = this.fireResistant; -- clone.maxStackSize = this.maxStackSize; -- clone.rarity = this.rarity; -- if (this.hasFood()) { -- clone.food = new CraftFoodComponent(this.food); -+ -+ final Map internalTags = new HashMap(); -+ this.serializeInternal(internalTags); -+ if (!internalTags.isEmpty()) { -+ CompoundTag internal = new CompoundTag(); -+ for (Map.Entry e : internalTags.entrySet()) { -+ internal.put(e.getKey(), e.getValue()); -+ } -+ try { -+ ByteArrayOutputStream buf = new ByteArrayOutputStream(); -+ NbtIo.writeCompressed(internal, buf); -+ builder.put("internal", Base64.getEncoder().encodeToString(buf.toByteArray())); -+ } catch (IOException ex) { -+ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ } - } -- if (this.hasTool()) { -- clone.tool = new CraftToolComponent(this.tool); -+ -+ // Paper start -+ final boolean canBreakAddToUnhandled = this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty(); -+ if (canBreakAddToUnhandled) { -+ this.unhandledTags.set(DataComponents.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS))); - } -- if (this.hasJukeboxPlayable()) { -- clone.jukebox = new CraftJukeboxComponent(this.jukebox); -+ final boolean canPlaceOnAddToUnhandled = this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty(); -+ if (canPlaceOnAddToUnhandled) { -+ this.unhandledTags.set(DataComponents.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON))); -+ } -+ // Paper end -+ if (!this.unhandledTags.isEmpty()) { -+ Tag unhandled = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), this.unhandledTags.build()).getOrThrow(IllegalStateException::new); -+ try { -+ ByteArrayOutputStream buf = new ByteArrayOutputStream(); -+ NbtIo.writeCompressed((CompoundTag) unhandled, buf); -+ builder.put("unhandled", Base64.getEncoder().encodeToString(buf.toByteArray())); -+ } catch (IOException ex) { -+ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ } - } -- clone.damage = this.damage; -- clone.maxDamage = this.maxDamage; -- clone.version = this.version; - // Paper start -- if (this.canPlaceOnPredicates != null) { -- clone.canPlaceOnPredicates = List.copyOf(this.canPlaceOnPredicates); -+ if (canBreakAddToUnhandled) { -+ this.unhandledTags.clear(DataComponents.CAN_BREAK); - } -- if (this.canBreakPredicates != null) { -- clone.canBreakPredicates = List.copyOf(this.canBreakPredicates); -+ if (canPlaceOnAddToUnhandled) { -+ this.unhandledTags.clear(DataComponents.CAN_PLACE_ON); - } - // Paper end -- return clone; -- } catch (CloneNotSupportedException e) { -- throw new Error(e); -- } -- } - -- @Override -- public final Map serialize() { -- ImmutableMap.Builder map = ImmutableMap.builder(); -- map.put(SerializableMeta.TYPE_FIELD, SerializableMeta.classMap.get(this.getClass())); -- this.serialize(map); -- return map.build(); -- } -+ if (!this.removedTags.isEmpty()) { -+ RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); -+ Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); - -- @Overridden -- ImmutableMap.Builder serialize(ImmutableMap.Builder builder) { -- if (this.hasDisplayName()) { -- builder.put(CraftMetaItem.NAME.BUKKIT, CraftChatMessage.toJSON(this.displayName)); -- } -+ List removedTags = new ArrayList<>(); -+ for (DataComponentType removed : this.removedTags) { -+ String componentKey = componentTypeRegistry.getResourceKey(removed).orElseThrow().location().toString(); - -- if (this.hasItemName()) { -- builder.put(CraftMetaItem.ITEM_NAME.BUKKIT, CraftChatMessage.toJSON(this.itemName)); -- } -- -- if (this.hasLore()) { -- // SPIGOT-7625: Convert lore to json before serializing it -- List jsonLore = new ArrayList<>(); -+ removedTags.add(componentKey); -+ } - -- for (Component component : this.lore) { -- jsonLore.add(CraftChatMessage.toJSON(component)); -+ builder.put("removed", removedTags); - } - -- builder.put(CraftMetaItem.LORE.BUKKIT, jsonLore); -- } -- -- if (this.hasCustomModelData()) { -- builder.put(CraftMetaItem.CUSTOM_MODEL_DATA.BUKKIT, this.customModelData); -- } -- if (this.hasBlockData()) { -- builder.put(CraftMetaItem.BLOCK_DATA.BUKKIT, this.blockData); -- } -- -- CraftMetaItem.serializeEnchantments(this.enchantments, builder, CraftMetaItem.ENCHANTMENTS); -- CraftMetaItem.serializeModifiers(this.attributeModifiers, builder, CraftMetaItem.ATTRIBUTES); -- -- if (this.hasRepairCost()) { -- builder.put(CraftMetaItem.REPAIR.BUKKIT, this.repairCost); -- } -- -- List hideFlags = new ArrayList(); -- for (ItemFlag hideFlagEnum : this.getItemFlags()) { -- hideFlags.add(CraftItemFlag.bukkitToString(hideFlagEnum)); -- } -- if (!hideFlags.isEmpty()) { -- builder.put(CraftMetaItem.HIDEFLAGS.BUKKIT, hideFlags); -- } -- -- if (this.isHideTooltip()) { -- builder.put(CraftMetaItem.HIDE_TOOLTIP.BUKKIT, this.hideTooltip); -- } -- -- if (this.isUnbreakable()) { -- builder.put(CraftMetaItem.UNBREAKABLE.BUKKIT, this.unbreakable); -- } -- -- if (this.hasEnchantmentGlintOverride()) { -- builder.put(CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.BUKKIT, this.enchantmentGlintOverride); -- } -- -- if (this.isFireResistant()) { -- builder.put(CraftMetaItem.FIRE_RESISTANT.BUKKIT, this.fireResistant); -- } -- -- if (this.hasMaxStackSize()) { -- builder.put(CraftMetaItem.MAX_STACK_SIZE.BUKKIT, this.maxStackSize); -- } -+ if (!this.persistentDataContainer.isEmpty()) { // Store custom tags, wrapped in their compound -+ builder.put(CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, this.persistentDataContainer.serialize()); -+ } - -- if (this.hasRarity()) { -- builder.put(CraftMetaItem.RARITY.BUKKIT, this.rarity.name()); -- } -+ if (this.customTag != null) { -+ try { -+ ByteArrayOutputStream buf = new ByteArrayOutputStream(); -+ NbtIo.writeCompressed(this.customTag, buf); -+ builder.put("custom", Base64.getEncoder().encodeToString(buf.toByteArray())); -+ } catch (IOException ex) { -+ Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ } -+ } - -- if (this.hasFood()) { -- builder.put(CraftMetaItem.FOOD.BUKKIT, this.food); -+ return builder; - } - -- if (this.hasTool()) { -- builder.put(CraftMetaItem.TOOL.BUKKIT, this.tool); -+ void serializeInternal(final Map unhandledTags) { - } - -- if (this.hasJukeboxPlayable()) { -- builder.put(CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, this.jukebox); -- } -+ static void serializeEnchantments(Map enchantments, ImmutableMap.Builder builder, ItemMetaKey key) { -+ if (enchantments == null || enchantments.isEmpty()) { -+ return; -+ } - -- if (this.hasDamage()) { -- builder.put(CraftMetaItem.DAMAGE.BUKKIT, this.damage); -- } -+ ImmutableMap.Builder enchants = ImmutableMap.builder(); -+ for (Map.Entry enchant : enchantments.entrySet()) { -+ enchants.put(CraftEnchantment.bukkitToString(enchant.getKey()), enchant.getValue()); -+ } - -- if (this.hasMaxDamage()) { -- builder.put(CraftMetaItem.MAX_DAMAGE.BUKKIT, this.maxDamage); -+ builder.put(key.BUKKIT, enchants.build()); - } - -- final Map internalTags = new HashMap(); -- this.serializeInternal(internalTags); -- if (!internalTags.isEmpty()) { -- CompoundTag internal = new CompoundTag(); -- for (Map.Entry e : internalTags.entrySet()) { -- internal.put(e.getKey(), e.getValue()); -- } -- try { -- ByteArrayOutputStream buf = new ByteArrayOutputStream(); -- NbtIo.writeCompressed(internal, buf); -- builder.put("internal", Base64.getEncoder().encodeToString(buf.toByteArray())); -- } catch (IOException ex) { -- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ static void serializeModifiers(Multimap modifiers, ImmutableMap.Builder builder, ItemMetaKey key) { -+ if (modifiers == null || modifiers.isEmpty()) { -+ return; - } -- } - -- // Paper start -- final boolean canBreakAddToUnhandled = this.canBreakPredicates != null && !this.canBreakPredicates.isEmpty(); -- if (canBreakAddToUnhandled) { -- this.unhandledTags.set(DataComponents.CAN_BREAK, new net.minecraft.world.item.AdventureModePredicate(this.canBreakPredicates, !this.hasItemFlag(ItemFlag.HIDE_DESTROYS))); -- } -- final boolean canPlaceOnAddToUnhandled = this.canPlaceOnPredicates != null && !this.canPlaceOnPredicates.isEmpty(); -- if (canPlaceOnAddToUnhandled) { -- this.unhandledTags.set(DataComponents.CAN_PLACE_ON, new net.minecraft.world.item.AdventureModePredicate(this.canPlaceOnPredicates, !this.hasItemFlag(ItemFlag.HIDE_PLACED_ON))); -- } -- // Paper end -- if (!this.unhandledTags.isEmpty()) { -- Tag unhandled = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), this.unhandledTags.build()).getOrThrow(IllegalStateException::new); -- try { -- ByteArrayOutputStream buf = new ByteArrayOutputStream(); -- NbtIo.writeCompressed((CompoundTag) unhandled, buf); -- builder.put("unhandled", Base64.getEncoder().encodeToString(buf.toByteArray())); -- } catch (IOException ex) { -- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ Map> mods = new LinkedHashMap<>(); -+ for (Map.Entry entry : modifiers.entries()) { -+ if (entry.getKey() == null) { -+ continue; -+ } -+ Collection modCollection = modifiers.get(entry.getKey()); -+ if (modCollection == null || modCollection.isEmpty()) { -+ continue; -+ } -+ mods.put(CraftAttribute.bukkitToString(entry.getKey()), new ArrayList<>(modCollection)); - } -+ builder.put(key.BUKKIT, mods); - } -- // Paper start -- if (canBreakAddToUnhandled) { -- this.unhandledTags.clear(DataComponents.CAN_BREAK); -- } -- if (canPlaceOnAddToUnhandled) { -- this.unhandledTags.clear(DataComponents.CAN_PLACE_ON); -- } -- // Paper end -- -- if (!this.removedTags.isEmpty()) { -- RegistryAccess registryAccess = CraftRegistry.getMinecraftRegistry(); -- Registry> componentTypeRegistry = registryAccess.registryOrThrow(Registries.DATA_COMPONENT_TYPE); -- -- List removedTags = new ArrayList<>(); -- for (DataComponentType removed : this.removedTags) { -- String componentKey = componentTypeRegistry.getResourceKey(removed).orElseThrow().location().toString(); - -- removedTags.add(componentKey); -+ static void safelyAdd(Iterable addFrom, Collection addTo, boolean possiblyJsonInput) { -+ if (addFrom == null) { -+ return; - } - -- builder.put("removed", removedTags); -- } -+ for (Object object : addFrom) { -+ // Paper start - support components -+ if(object instanceof net.md_5.bungee.api.chat.BaseComponent[] baseComponentArr) { -+ addTo.add(CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(baseComponentArr))); -+ } else -+ // Paper end -+ if (!(object instanceof String)) { -+ if (object != null) { -+ // SPIGOT-7399: Null check via if is important, -+ // otherwise object.getClass().getName() could throw an error for a valid argument -> when it is null which is valid, -+ // when using Preconditions -+ throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); -+ } - -- if (!this.persistentDataContainer.isEmpty()) { // Store custom tags, wrapped in their compound -- builder.put(CraftMetaItem.BUKKIT_CUSTOM_TAG.BUKKIT, this.persistentDataContainer.serialize()); -- } -+ addTo.add(Component.empty()); -+ } else { -+ String entry = object.toString(); -+ Component component = (possiblyJsonInput) ? CraftChatMessage.fromJSONOrString(entry) : CraftChatMessage.fromStringOrNull(entry); - -- if (this.customTag != null) { -- try { -- ByteArrayOutputStream buf = new ByteArrayOutputStream(); -- NbtIo.writeCompressed(this.customTag, buf); -- builder.put("custom", Base64.getEncoder().encodeToString(buf.toByteArray())); -- } catch (IOException ex) { -- Logger.getLogger(CraftMetaItem.class.getName()).log(Level.SEVERE, null, ex); -+ if (component != null) { -+ addTo.add(component); -+ } else { -+ addTo.add(Component.empty()); -+ } -+ } - } - } - -- return builder; -- } -- -- void serializeInternal(final Map unhandledTags) { -- } -- -- static void serializeEnchantments(Map enchantments, ImmutableMap.Builder builder, ItemMetaKey key) { -- if (enchantments == null || enchantments.isEmpty()) { -- return; -- } -- -- ImmutableMap.Builder enchants = ImmutableMap.builder(); -- for (Map.Entry enchant : enchantments.entrySet()) { -- enchants.put(CraftEnchantment.bukkitToString(enchant.getKey()), enchant.getValue()); -- } -- -- builder.put(key.BUKKIT, enchants.build()); -- } -- -- static void serializeModifiers(Multimap modifiers, ImmutableMap.Builder builder, ItemMetaKey key) { -- if (modifiers == null || modifiers.isEmpty()) { -- return; -- } -- -- Map> mods = new LinkedHashMap<>(); -- for (Map.Entry entry : modifiers.entries()) { -- if (entry.getKey() == null) { -- continue; -- } -- Collection modCollection = modifiers.get(entry.getKey()); -- if (modCollection == null || modCollection.isEmpty()) { -- continue; -+ static boolean checkConflictingEnchants(Map enchantments, Enchantment ench) { -+ if (enchantments == null || enchantments.isEmpty()) { -+ return false; - } -- mods.put(CraftAttribute.bukkitToString(entry.getKey()), new ArrayList<>(modCollection)); -- } -- builder.put(key.BUKKIT, mods); -- } - -- static void safelyAdd(Iterable addFrom, Collection addTo, boolean possiblyJsonInput) { -- if (addFrom == null) { -- return; -- } -- -- for (Object object : addFrom) { -- // Paper start - support components -- if(object instanceof net.md_5.bungee.api.chat.BaseComponent[] baseComponentArr) { -- addTo.add(CraftChatMessage.fromJSON(net.md_5.bungee.chat.ComponentSerializer.toString(baseComponentArr))); -- } else -- // Paper end -- if (!(object instanceof String)) { -- if (object != null) { -- // SPIGOT-7399: Null check via if is important, -- // otherwise object.getClass().getName() could throw an error for a valid argument -> when it is null which is valid, -- // when using Preconditions -- throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName()); -- } -- -- addTo.add(Component.empty()); -- } else { -- String entry = object.toString(); -- Component component = (possiblyJsonInput) ? CraftChatMessage.fromJSONOrString(entry) : CraftChatMessage.fromStringOrNull(entry); -- -- if (component != null) { -- addTo.add(component); -- } else { -- addTo.add(Component.empty()); -+ for (Enchantment enchant : enchantments.keySet()) { -+ if (enchant.conflictsWith(ench)) { -+ return true; - } - } -- } -- } - -- static boolean checkConflictingEnchants(Map enchantments, Enchantment ench) { -- if (enchantments == null || enchantments.isEmpty()) { - return false; - } + Set, Optional>> keys = tag.entrySet(); + for (Map.Entry, Optional> key : keys) { + // Paper start - don't lose unhandled tags + if (key.getValue().isEmpty()) { + this.unhandledTags.remove(key.getKey()); +- } else if (!CraftMetaItem.getHandledTags().contains(key.getKey())) { ++ } else if (!handledTags.contains(key.getKey())) { // Paper - improve checking handled data component types + // Paper end - don't lose unhandled tags + key.getValue().ifPresent((value) -> { + this.unhandledTags.set((DataComponentType) key.getKey(), value); +@@ -2047,67 +2054,75 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + this.version = version; + } -- for (Enchantment enchant : enchantments.keySet()) { -- if (enchant.conflictsWith(ench)) { -- return true; -- } -- } -- -- return false; -- } -- -- @Override -- public final String toString() { -- return SerializableMeta.classMap.get(this.getClass()) + "_META:" + this.serialize(); // TODO: cry -- } -- -- public int getVersion() { -- return this.version; -- } -- -- @Override -- public void setVersion(int version) { -- this.version = version; -- } -- - public static Set getHandledTags() { - synchronized (CraftMetaItem.HANDLED_TAGS) { - if (CraftMetaItem.HANDLED_TAGS.isEmpty()) { @@ -3372,86 +547,72 @@ index d29b8c6851aad227eb8f12012903e0ddd5531755..11c6c8d9c14fb31d1819a5c61e3b743b - )); - } - return CraftMetaItem.HANDLED_TAGS; -+ @Override -+ public final String toString() { -+ return SerializableMeta.classMap.get(this.getClass()) + "_META:" + this.serialize(); // TODO: cry -+ } -+ -+ public int getVersion() { -+ return this.version; -+ } -+ -+ @Override -+ public void setVersion(int version) { -+ this.version = version; -+ } -+ -+ // Paper start - improve checking handled tags -+ @org.jetbrains.annotations.VisibleForTesting -+ public static final Map, Set>> HANDLED_DCTS_PER_TYPE = new HashMap<>(); -+ private static final Set> DEFAULT_HANDLED_DCTS = Set.of( -+ CraftMetaItem.NAME.TYPE, -+ CraftMetaItem.ITEM_NAME.TYPE, -+ CraftMetaItem.LORE.TYPE, -+ CraftMetaItem.CUSTOM_MODEL_DATA.TYPE, -+ CraftMetaItem.BLOCK_DATA.TYPE, -+ CraftMetaItem.REPAIR.TYPE, -+ CraftMetaItem.ENCHANTMENTS.TYPE, -+ CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP.TYPE, -+ CraftMetaItem.HIDE_TOOLTIP.TYPE, -+ CraftMetaItem.UNBREAKABLE.TYPE, -+ CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.TYPE, -+ CraftMetaItem.FIRE_RESISTANT.TYPE, -+ CraftMetaItem.MAX_STACK_SIZE.TYPE, -+ CraftMetaItem.RARITY.TYPE, -+ CraftMetaItem.FOOD.TYPE, -+ CraftMetaItem.TOOL.TYPE, -+ CraftMetaItem.JUKEBOX_PLAYABLE.TYPE, -+ CraftMetaItem.DAMAGE.TYPE, -+ CraftMetaItem.MAX_DAMAGE.TYPE, -+ CraftMetaItem.CUSTOM_DATA.TYPE, -+ CraftMetaItem.ATTRIBUTES.TYPE, -+ CraftMetaItem.CAN_PLACE_ON.TYPE, // Paper -+ CraftMetaItem.CAN_BREAK.TYPE // Paper -+ ); -+ public static Set> getTopLevelHandledDcts(final Class clazz) { -+ synchronized (HANDLED_DCTS_PER_TYPE) { -+ if (HANDLED_DCTS_PER_TYPE.isEmpty()) { -+ final Map, Set>> map = new HashMap<>(); -+ map.put(CraftMetaArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE)); -+ map.put(CraftMetaArmorStand.class, Set.of(CraftMetaArmorStand.ENTITY_TAG.TYPE)); -+ map.put(CraftMetaAxolotlBucket.class, Set.of(CraftMetaAxolotlBucket.ENTITY_TAG.TYPE, CraftMetaAxolotlBucket.BUCKET_ENTITY_TAG.TYPE)); -+ map.put(CraftMetaBanner.class, Set.of(/*CraftMetaBlockState.BLOCK_ENTITY_TAG.NBT, */CraftMetaBanner.PATTERNS.TYPE)); // banner uses same tag as block state -+ map.put(CraftMetaBlockState.class, Set.of(CraftMetaBlockState.BLOCK_ENTITY_TAG.TYPE)); -+ map.put(CraftMetaBook.class, Set.of(CraftMetaBook.BOOK_CONTENT.TYPE)); -+ map.put(CraftMetaBookSigned.class, Set.of(CraftMetaBookSigned.BOOK_CONTENT.TYPE)); -+ map.put(CraftMetaBundle.class, Set.of(CraftMetaBundle.ITEMS.TYPE)); -+ map.put(CraftMetaCharge.class, Set.of(CraftMetaCharge.EXPLOSION.TYPE)); -+ map.put(CraftMetaColorableArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE, CraftMetaLeatherArmor.COLOR.TYPE)); -+ map.put(CraftMetaCompass.class, Set.of(CraftMetaCompass.LODESTONE_TARGET.TYPE)); -+ map.put(CraftMetaCrossbow.class, Set.of(CraftMetaCrossbow.CHARGED_PROJECTILES.TYPE)); -+ map.put(CraftMetaEnchantedBook.class, Set.of(CraftMetaEnchantedBook.STORED_ENCHANTMENTS.TYPE)); -+ map.put(CraftMetaEntityTag.class, Set.of(CraftMetaEntityTag.ENTITY_TAG.TYPE)); -+ map.put(CraftMetaFirework.class, Set.of(CraftMetaFirework.FIREWORKS.TYPE)); -+ map.put(CraftMetaKnowledgeBook.class, Set.of(CraftMetaKnowledgeBook.BOOK_RECIPES.TYPE)); -+ map.put(CraftMetaLeatherArmor.class, Set.of(CraftMetaLeatherArmor.COLOR.TYPE)); -+ map.put(CraftMetaMap.class, Set.of(CraftMetaMap.MAP_COLOR.TYPE, CraftMetaMap.MAP_POST_PROCESSING.TYPE, CraftMetaMap.MAP_ID.TYPE)); -+ map.put(CraftMetaMusicInstrument.class, Set.of(CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT.TYPE)); -+ map.put(CraftMetaOminousBottle.class, Set.of(CraftMetaOminousBottle.OMINOUS_BOTTLE_AMPLIFIER.TYPE)); -+ map.put(CraftMetaPotion.class, Set.of(CraftMetaPotion.POTION_CONTENTS.TYPE)); -+ map.put(CraftMetaSkull.class, Set.of(CraftMetaSkull.SKULL_PROFILE.TYPE, CraftMetaSkull.NOTE_BLOCK_SOUND.TYPE)); -+ map.put(CraftMetaSpawnEgg.class, Set.of(CraftMetaSpawnEgg.ENTITY_TAG.TYPE)); -+ map.put(CraftMetaSuspiciousStew.class, Set.of(CraftMetaSuspiciousStew.EFFECTS.TYPE)); -+ map.put(CraftMetaTropicalFishBucket.class, Set.of(CraftMetaTropicalFishBucket.ENTITY_TAG.TYPE, CraftMetaTropicalFishBucket.BUCKET_ENTITY_TAG.TYPE)); -+ -+ for (final Map.Entry, Set>> entry : map.entrySet()) { -+ final ArrayList> topLevelTags = new ArrayList<>(entry.getValue()); -+ // add tags common to CraftMetaItem to all -+ topLevelTags.addAll(DEFAULT_HANDLED_DCTS); -+ HANDLED_DCTS_PER_TYPE.put(entry.getKey(), Set.copyOf(topLevelTags)); -+ } -+ } -+ return HANDLED_DCTS_PER_TYPE.getOrDefault(clazz, DEFAULT_HANDLED_DCTS); ++ // Paper start - improve checking handled tags ++ @org.jetbrains.annotations.VisibleForTesting ++ public static final Map, Set>> HANDLED_DCTS_PER_TYPE = new HashMap<>(); ++ private static final Set> DEFAULT_HANDLED_DCTS = Set.of( ++ CraftMetaItem.NAME.TYPE, ++ CraftMetaItem.ITEM_NAME.TYPE, ++ CraftMetaItem.LORE.TYPE, ++ CraftMetaItem.CUSTOM_MODEL_DATA.TYPE, ++ CraftMetaItem.BLOCK_DATA.TYPE, ++ CraftMetaItem.REPAIR.TYPE, ++ CraftMetaItem.ENCHANTMENTS.TYPE, ++ CraftMetaItem.HIDE_ADDITIONAL_TOOLTIP.TYPE, ++ CraftMetaItem.HIDE_TOOLTIP.TYPE, ++ CraftMetaItem.UNBREAKABLE.TYPE, ++ CraftMetaItem.ENCHANTMENT_GLINT_OVERRIDE.TYPE, ++ CraftMetaItem.FIRE_RESISTANT.TYPE, ++ CraftMetaItem.MAX_STACK_SIZE.TYPE, ++ CraftMetaItem.RARITY.TYPE, ++ CraftMetaItem.FOOD.TYPE, ++ CraftMetaItem.TOOL.TYPE, ++ CraftMetaItem.JUKEBOX_PLAYABLE.TYPE, ++ CraftMetaItem.DAMAGE.TYPE, ++ CraftMetaItem.MAX_DAMAGE.TYPE, ++ CraftMetaItem.CUSTOM_DATA.TYPE, ++ CraftMetaItem.ATTRIBUTES.TYPE, ++ CraftMetaItem.CAN_PLACE_ON.TYPE, // Paper ++ CraftMetaItem.CAN_BREAK.TYPE // Paper ++ ); ++ public static Set> getTopLevelHandledDcts(final Class clazz) { ++ synchronized (HANDLED_DCTS_PER_TYPE) { ++ if (HANDLED_DCTS_PER_TYPE.isEmpty()) { ++ final Map, Set>> map = new HashMap<>(); ++ map.put(CraftMetaArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE)); ++ map.put(CraftMetaArmorStand.class, Set.of(CraftMetaArmorStand.ENTITY_TAG.TYPE)); ++ map.put(CraftMetaAxolotlBucket.class, Set.of(CraftMetaAxolotlBucket.ENTITY_TAG.TYPE, CraftMetaAxolotlBucket.BUCKET_ENTITY_TAG.TYPE)); ++ map.put(CraftMetaBanner.class, Set.of(/*CraftMetaBlockState.BLOCK_ENTITY_TAG.NBT, */CraftMetaBanner.PATTERNS.TYPE)); // banner uses same tag as block state ++ map.put(CraftMetaBlockState.class, Set.of(CraftMetaBlockState.BLOCK_ENTITY_TAG.TYPE)); ++ map.put(CraftMetaBook.class, Set.of(CraftMetaBook.BOOK_CONTENT.TYPE)); ++ map.put(CraftMetaBookSigned.class, Set.of(CraftMetaBookSigned.BOOK_CONTENT.TYPE)); ++ map.put(CraftMetaBundle.class, Set.of(CraftMetaBundle.ITEMS.TYPE)); ++ map.put(CraftMetaCharge.class, Set.of(CraftMetaCharge.EXPLOSION.TYPE)); ++ map.put(CraftMetaColorableArmor.class, Set.of(CraftMetaArmor.TRIM.TYPE, CraftMetaLeatherArmor.COLOR.TYPE)); ++ map.put(CraftMetaCompass.class, Set.of(CraftMetaCompass.LODESTONE_TARGET.TYPE)); ++ map.put(CraftMetaCrossbow.class, Set.of(CraftMetaCrossbow.CHARGED_PROJECTILES.TYPE)); ++ map.put(CraftMetaEnchantedBook.class, Set.of(CraftMetaEnchantedBook.STORED_ENCHANTMENTS.TYPE)); ++ map.put(CraftMetaEntityTag.class, Set.of(CraftMetaEntityTag.ENTITY_TAG.TYPE)); ++ map.put(CraftMetaFirework.class, Set.of(CraftMetaFirework.FIREWORKS.TYPE)); ++ map.put(CraftMetaKnowledgeBook.class, Set.of(CraftMetaKnowledgeBook.BOOK_RECIPES.TYPE)); ++ map.put(CraftMetaLeatherArmor.class, Set.of(CraftMetaLeatherArmor.COLOR.TYPE)); ++ map.put(CraftMetaMap.class, Set.of(CraftMetaMap.MAP_COLOR.TYPE, CraftMetaMap.MAP_POST_PROCESSING.TYPE, CraftMetaMap.MAP_ID.TYPE)); ++ map.put(CraftMetaMusicInstrument.class, Set.of(CraftMetaMusicInstrument.GOAT_HORN_INSTRUMENT.TYPE)); ++ map.put(CraftMetaOminousBottle.class, Set.of(CraftMetaOminousBottle.OMINOUS_BOTTLE_AMPLIFIER.TYPE)); ++ map.put(CraftMetaPotion.class, Set.of(CraftMetaPotion.POTION_CONTENTS.TYPE)); ++ map.put(CraftMetaSkull.class, Set.of(CraftMetaSkull.SKULL_PROFILE.TYPE, CraftMetaSkull.NOTE_BLOCK_SOUND.TYPE)); ++ map.put(CraftMetaSpawnEgg.class, Set.of(CraftMetaSpawnEgg.ENTITY_TAG.TYPE)); ++ map.put(CraftMetaSuspiciousStew.class, Set.of(CraftMetaSuspiciousStew.EFFECTS.TYPE)); ++ map.put(CraftMetaTropicalFishBucket.class, Set.of(CraftMetaTropicalFishBucket.ENTITY_TAG.TYPE, CraftMetaTropicalFishBucket.BUCKET_ENTITY_TAG.TYPE)); ++ ++ for (final Map.Entry, Set>> entry : map.entrySet()) { ++ final ArrayList> topLevelTags = new ArrayList<>(entry.getValue()); ++ // add tags common to CraftMetaItem to all ++ topLevelTags.addAll(DEFAULT_HANDLED_DCTS); ++ HANDLED_DCTS_PER_TYPE.put(entry.getKey(), Set.copyOf(topLevelTags)); ++ } ++ } ++ return HANDLED_DCTS_PER_TYPE.getOrDefault(clazz, DEFAULT_HANDLED_DCTS); } } + // Paper end - improve checking handled data component types diff --git a/patches/server/0970-General-ItemMeta-fixes.patch b/patches/server/0970-General-ItemMeta-fixes.patch index 92d50c3f17e7..cc18be892476 100644 --- a/patches/server/0970-General-ItemMeta-fixes.patch +++ b/patches/server/0970-General-ItemMeta-fixes.patch @@ -457,19 +457,6 @@ index e064af399dcae40b4f35aa993d356b1462f91d6c..27a275f324891e395bf3fd3038c0b9a7 static final int MAX_PAGE_LENGTH = WritableBookContent.PAGE_EDIT_LENGTH; // SPIGOT-6911: Use Minecraft limits // We store the pages in their raw original text representation. See SPIGOT-5063, SPIGOT-5350, SPIGOT-3206 -diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -index 806c1cbee7c4e23eee38c8f400ec2d924c9a360c..bf7293835dbb4e9c55a51655ca5d85bc87c63d1d 100644 ---- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBookSigned.java -@@ -129,7 +129,7 @@ public class CraftMetaBookSigned extends CraftMetaItem implements BookMeta { - for (Component page : this.pages) { - list.add(Filterable.passThrough(page)); - } -- itemData.put(CraftMetaBookSigned.BOOK_CONTENT, new WrittenBookContent(Filterable.from(FilteredText.passThrough(this.title)), this.author, this.generation, list, this.resolved)); -+ itemData.put(CraftMetaBookSigned.BOOK_CONTENT, new WrittenBookContent(Filterable.from(FilteredText.passThrough(this.title == null ? "" : this.title)), this.author == null ? "" : this.author, this.generation, list, this.resolved)); - } - } - diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java index 2736a87a6c481da0575e6e29ea08faa539c24378..51da0db4da3549efd69f367e28450408968fa8d0 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBundle.java @@ -788,7 +775,7 @@ index 9600b23666668d7d581e2920a4e03e59cc2339fb..0eceacbb096481d3bd31f5f99e964c88 } } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index 11c6c8d9c14fb31d1819a5c61e3b743b0b6c6d65..a82b8e123d3df343f643bdcf007bc3632518c6a1 100644 +index 58da8cb19a8444c634cbc1f39e93503ca8e2ecab..776f4dcc0b61a5b8ee4020a283cfcfacefbe682e 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -182,9 +182,10 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { @@ -835,306 +822,307 @@ index 11c6c8d9c14fb31d1819a5c61e3b743b0b6c6d65..a82b8e123d3df343f643bdcf007bc363 this.displayName = component; }); @@ -802,7 +808,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - Map mods = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); - Multimap result = LinkedHashMultimap.create(); - if (mods == null) { -- return result; -+ return null; // Paper - null is different from an empty map - } + Map mods = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true); + Multimap result = LinkedHashMultimap.create(); + if (mods == null) { +- return result; ++ return null; // Paper - null is different from an empty map + } - for (Object obj : mods.keySet()) { -@@ -909,7 +915,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - itemTag.put(CraftMetaItem.DAMAGE, this.damage); - } + for (Object obj : mods.keySet()) { +@@ -905,7 +911,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + itemTag.put(CraftMetaItem.JUKEBOX_PLAYABLE, this.jukebox.getHandle()); + } -- if (this.hasMaxDamage()) { -+ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage - itemTag.put(CraftMetaItem.MAX_DAMAGE, this.maxDamage); - } +- if (this.hasDamage()) { ++ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage + itemTag.put(CraftMetaItem.DAMAGE, this.damage); + } @@ -970,10 +976,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - } + } - void applyModifiers(Multimap modifiers, CraftMetaItem.Applicator tag) { -- if (modifiers == null || modifiers.isEmpty()) { -- if (this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES)) { -- tag.put(CraftMetaItem.ATTRIBUTES, new ItemAttributeModifiers(Collections.emptyList(), false)); -- } -+ if (modifiers == null/* || modifiers.isEmpty()*/) { // Paper - empty modifiers has a specific meaning, they should still be saved -+ // Paper - don't save ItemFlag if the underlying data isn't present - return; - } + void applyModifiers(Multimap modifiers, CraftMetaItem.Applicator tag) { +- if (modifiers == null || modifiers.isEmpty()) { +- if (this.hasItemFlag(ItemFlag.HIDE_ATTRIBUTES)) { +- tag.put(CraftMetaItem.ATTRIBUTES, new ItemAttributeModifiers(Collections.emptyList(), false)); +- } ++ if (modifiers == null/* || modifiers.isEmpty()*/) { // Paper - empty modifiers has a specific meaning, they should still be saved ++ // Paper - don't save ItemFlag if the underlying data isn't present + return; + } @@ -1010,7 +1014,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Overridden - boolean isEmpty() { -- return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper -+ return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasJukeboxPlayable() || this.hasDamageValue() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper - } + @Overridden + boolean isEmpty() { +- return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasDamage() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper ++ return !(this.hasDisplayName() || this.hasItemName() || this.hasLocalizedName() || this.hasEnchants() || (this.lore != null) || this.hasCustomModelData() || this.hasBlockData() || this.hasRepairCost() || !this.unhandledTags.build().isEmpty() || !this.removedTags.isEmpty() || !this.persistentDataContainer.isEmpty() || this.hideFlag != 0 || this.isHideTooltip() || this.isUnbreakable() || this.hasEnchantmentGlintOverride() || this.isFireResistant() || this.hasMaxStackSize() || this.hasRarity() || this.hasFood() || this.hasTool() || this.hasJukeboxPlayable() || this.hasDamageValue() || this.hasMaxDamage() || this.hasAttributeModifiers() || this.customTag != null || this.canPlaceOnPredicates != null || this.canBreakPredicates != null); // Paper + } - // Paper start + // Paper start @@ -1106,6 +1110,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public void lore(final List lore) { -+ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines - this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(lore) : null; - } - // Paper end + @Override + public void lore(final List lore) { ++ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines + this.lore = lore != null ? io.papermc.paper.adventure.PaperAdventure.asVanilla(lore) : null; + } + // Paper end @@ -1164,7 +1169,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public void removeEnchantments() { - if (this.hasEnchants()) { -- this.enchantments.clear(); -+ this.enchantments = null; // Paper - Correctly clear enchantments - } + @Override + public void removeEnchantments() { + if (this.hasEnchants()) { +- this.enchantments.clear(); ++ this.enchantments = null; // Paper - Correctly clear enchantments } + } @@ -1230,6 +1235,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - // Paper end - @Override - public void setLore(List lore) { -+ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines - if (lore == null || lore.isEmpty()) { - this.lore = null; - } else { + // Paper end + @Override + public void setLore(List lore) { ++ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines + if (lore == null || lore.isEmpty()) { + this.lore = null; + } else { @@ -1245,6 +1251,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - // Paper start - @Override - public void setLoreComponents(List lore) { -+ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines - if (lore == null) { - this.lore = null; - } else { + // Paper start + @Override + public void setLoreComponents(List lore) { ++ Preconditions.checkArgument(lore == null || lore.size() <= ItemLore.MAX_LINES, "lore cannot have more than %s lines", ItemLore.MAX_LINES); // Paper - limit lore lines + if (lore == null) { + this.lore = null; + } else { @@ -1386,7 +1393,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public FoodComponent getFood() { -- return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, 0, Optional.empty(), Collections.emptyList())); -+ return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, FoodProperties.DEFAULT_EAT_SECONDS, Optional.empty(), Collections.emptyList())); // Paper - create a valid food properties - } + @Override + public FoodComponent getFood() { +- return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, 0, Optional.empty(), Collections.emptyList())); ++ return (this.hasFood()) ? new CraftFoodComponent(this.food) : new CraftFoodComponent(new FoodProperties(0, 0, false, FoodProperties.DEFAULT_EAT_SECONDS, Optional.empty(), Collections.emptyList())); // Paper - create a valid food properties + } - @Override + @Override @@ -1442,7 +1449,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public Multimap getAttributeModifiers(@Nullable EquipmentSlot slot) { -- this.checkAttributeList(); -+ if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components - SetMultimap result = LinkedHashMultimap.create(); - for (Map.Entry entry : this.attributeModifiers.entries()) { - if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + @Override + public Multimap getAttributeModifiers(@Nullable EquipmentSlot slot) { +- this.checkAttributeList(); ++ if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components + SetMultimap result = LinkedHashMultimap.create(); + for (Map.Entry entry : this.attributeModifiers.entries()) { + if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { @@ -1455,6 +1462,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public Collection getAttributeModifiers(@Nonnull Attribute attribute) { - Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -+ if (this.attributeModifiers == null) return null; // Paper - fix NPE - return this.attributeModifiers.containsKey(attribute) ? ImmutableList.copyOf(this.attributeModifiers.get(attribute)) : null; - } + @Override + public Collection getAttributeModifiers(@Nonnull Attribute attribute) { + Preconditions.checkNotNull(attribute, "Attribute cannot be null"); ++ if (this.attributeModifiers == null) return null; // Paper - fix NPE + return this.attributeModifiers.containsKey(attribute) ? ImmutableList.copyOf(this.attributeModifiers.get(attribute)) : null; + } @@ -1462,10 +1470,12 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - public boolean addAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { - Preconditions.checkNotNull(attribute, "Attribute cannot be null"); - Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); -- this.checkAttributeList(); -+ if (this.attributeModifiers != null) { // Paper - for (Map.Entry entry : this.attributeModifiers.entries()) { - Preconditions.checkArgument(!(entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine - } -+ } // Paper -+ this.checkAttributeList(); // Paper - moved down - return this.attributeModifiers.put(attribute, modifier); + public boolean addAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { + Preconditions.checkNotNull(attribute, "Attribute cannot be null"); + Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); +- this.checkAttributeList(); ++ if (this.attributeModifiers != null) { // Paper + for (Map.Entry entry : this.attributeModifiers.entries()) { + Preconditions.checkArgument(!(entry.getValue().getKey().equals(modifier.getKey()) && entry.getKey() == attribute), "Cannot register AttributeModifier. Modifier is already applied! %s", modifier); // Paper - attribute modifiers with same namespaced key but on different attributes are fine } ++ } // Paper ++ this.checkAttributeList(); // Paper - moved down + return this.attributeModifiers.put(attribute, modifier); + } @@ -1476,8 +1486,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - return; - } + return; + } -- this.checkAttributeList(); -- this.attributeModifiers.clear(); -+ // Paper start - fix modifiers meta -+ if (this.attributeModifiers != null) { -+ this.attributeModifiers.clear(); -+ } -+ // Paper end +- this.checkAttributeList(); +- this.attributeModifiers.clear(); ++ // Paper start - fix modifiers meta ++ if (this.attributeModifiers != null) { ++ this.attributeModifiers.clear(); ++ } ++ // Paper end - Iterator> iterator = attributeModifiers.entries().iterator(); - while (iterator.hasNext()) { + Iterator> iterator = attributeModifiers.entries().iterator(); + while (iterator.hasNext()) { @@ -1487,6 +1500,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - iterator.remove(); - continue; - } -+ this.checkAttributeList(); // Paper - moved down - this.attributeModifiers.put(next.getKey(), next.getValue()); + iterator.remove(); + continue; } ++ this.checkAttributeList(); // Paper - moved down + this.attributeModifiers.put(next.getKey(), next.getValue()); } + } @@ -1494,13 +1508,13 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public boolean removeAttributeModifier(@Nonnull Attribute attribute) { - Preconditions.checkNotNull(attribute, "Attribute cannot be null"); -- this.checkAttributeList(); -+ if (this.attributeModifiers == null) return false; // Paper - return !this.attributeModifiers.removeAll(attribute).isEmpty(); - } + @Override + public boolean removeAttributeModifier(@Nonnull Attribute attribute) { + Preconditions.checkNotNull(attribute, "Attribute cannot be null"); +- this.checkAttributeList(); ++ if (this.attributeModifiers == null) return false; // Paper + return !this.attributeModifiers.removeAll(attribute).isEmpty(); + } - @Override - public boolean removeAttributeModifier(@Nullable EquipmentSlot slot) { -- this.checkAttributeList(); -+ if (this.attributeModifiers == null) return false; // Paper - int removed = 0; - Iterator> iter = this.attributeModifiers.entries().iterator(); + @Override + public boolean removeAttributeModifier(@Nullable EquipmentSlot slot) { +- this.checkAttributeList(); ++ if (this.attributeModifiers == null) return false; // Paper + int removed = 0; + Iterator> iter = this.attributeModifiers.entries().iterator(); @@ -1520,7 +1534,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - public boolean removeAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { - Preconditions.checkNotNull(attribute, "Attribute cannot be null"); - Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); -- this.checkAttributeList(); -+ if (this.attributeModifiers == null) return false; // Paper - int removed = 0; - Iterator> iter = this.attributeModifiers.entries().iterator(); + public boolean removeAttributeModifier(@Nonnull Attribute attribute, @Nonnull AttributeModifier modifier) { + Preconditions.checkNotNull(attribute, "Attribute cannot be null"); + Preconditions.checkNotNull(modifier, "AttributeModifier cannot be null"); +- this.checkAttributeList(); ++ if (this.attributeModifiers == null) return false; // Paper + int removed = 0; + Iterator> iter = this.attributeModifiers.entries().iterator(); @@ -1542,7 +1556,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public String getAsString() { -- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); -+ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator() {}; // Paper - support updating profile after resolving it - this.applyToItem(tag); - DataComponentPatch patch = tag.build(); - Tag nbt = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), patch).getOrThrow(); + @Override + public String getAsString() { +- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); ++ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator() {}; // Paper - support updating profile after resolving it + this.applyToItem(tag); + DataComponentPatch patch = tag.build(); + Tag nbt = DataComponentPatch.CODEC.encodeStart(MinecraftServer.getDefaultRegistryAccess().createSerializationContext(NbtOps.INSTANCE), patch).getOrThrow(); @@ -1551,7 +1565,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public String getAsComponentString() { -- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); -+ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator() {}; // Paper - support updating profile after resolving it - this.applyToItem(tag); - DataComponentPatch patch = tag.build(); + @Override + public String getAsComponentString() { +- CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator(); ++ CraftMetaItem.Applicator tag = new CraftMetaItem.Applicator() {}; // Paper + this.applyToItem(tag); + DataComponentPatch patch = tag.build(); @@ -1591,6 +1605,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (first == null || second == null) { + if (first == null || second == null) { + return false; + } ++ if (first.isEmpty() && second.isEmpty()) return true; // Paper - empty modifiers are equivalent + for (Map.Entry entry : first.entries()) { + if (!second.containsEntry(entry.getKey(), entry.getValue())) { return false; - } -+ if (first.isEmpty() && second.isEmpty()) return true; // Paper - empty modifiers are equivalent - for (Map.Entry entry : first.entries()) { - if (!second.containsEntry(entry.getKey(), entry.getValue())) { - return false; @@ -1606,19 +1621,33 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public boolean hasDamage() { -- return this.damage > 0; -+ return this.damage != null && this.damage > 0; // Paper - null check - } + @Override + public boolean hasDamage() { +- return this.damage > 0; ++ return this.damage != null && this.damage > 0; // Paper - null check + } - @Override - public int getDamage() { -- return this.damage; -+ return this.damage == null ? 0 : this.damage; // Paper - null check - } + @Override + public int getDamage() { +- return this.damage; ++ return this.damage == null ? 0 : this.damage; // Paper - null check + } - @Override - public void setDamage(int damage) { -+ Preconditions.checkArgument(damage >= 0, "Damage cannot be negative"); // Paper -+ Preconditions.checkArgument(!this.hasMaxDamage() || damage <= this.maxDamage, "Damage cannot exceed max damage"); // Paper - this.damage = damage; - } + @Override + public void setDamage(int damage) { ++ Preconditions.checkArgument(damage >= 0, "Damage cannot be negative"); // Paper ++ Preconditions.checkArgument(!this.hasMaxDamage() || damage <= this.maxDamage, "Damage cannot exceed max damage"); // Paper + this.damage = damage; + } -+ // Paper start - preserve empty/0 damage -+ @Override -+ public boolean hasDamageValue() { -+ return this.damage != null; -+ } ++ // Paper start - preserve empty/0 damage ++ @Override ++ public boolean hasDamageValue() { ++ return this.damage != null; ++ } + -+ @Override -+ public void resetDamage() { -+ this.damage = null; -+ } -+ // Paper end - preserve empty/0 damage ++ @Override ++ public void resetDamage() { ++ this.damage = null; ++ } ++ // Paper end - preserve empty/0 damage + - @Override - public boolean hasMaxDamage() { - return this.maxDamage != null; + @Override + public boolean hasMaxDamage() { + return this.maxDamage != null; @@ -1632,6 +1661,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - @Override - public void setMaxDamage(Integer maxDamage) { -+ Preconditions.checkArgument(maxDamage == null || maxDamage > 0, "Max damage should be positive"); // Paper - this.maxDamage = maxDamage; - } + @Override + public void setMaxDamage(Integer maxDamage) { ++ Preconditions.checkArgument(maxDamage == null || maxDamage > 0, "Max damage should be positive"); // Paper + this.maxDamage = maxDamage; + } @@ -1663,7 +1693,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - && (this.hasCustomModelData() ? that.hasCustomModelData() && this.customModelData.equals(that.customModelData) : !that.hasCustomModelData()) - && (this.hasBlockData() ? that.hasBlockData() && this.blockData.equals(that.blockData) : !that.hasBlockData()) - && (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost()) -- && (this.hasAttributeModifiers() ? that.hasAttributeModifiers() && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : !that.hasAttributeModifiers()) + && (this.hasCustomModelData() ? that.hasCustomModelData() && this.customModelData.equals(that.customModelData) : !that.hasCustomModelData()) + && (this.hasBlockData() ? that.hasBlockData() && this.blockData.equals(that.blockData) : !that.hasBlockData()) + && (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost()) +- && (this.hasAttributeModifiers() ? that.hasAttributeModifiers() && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : !that.hasAttributeModifiers()) + && (this.attributeModifiers != null ? that.attributeModifiers != null && CraftMetaItem.compareModifiers(this.attributeModifiers, that.attributeModifiers) : that.attributeModifiers == null) // Paper - track only null modifiers - && (this.unhandledTags.equals(that.unhandledTags)) - && (this.removedTags.equals(that.removedTags)) - && (Objects.equals(this.customTag, that.customTag)) + && (this.unhandledTags.equals(that.unhandledTags)) + && (this.removedTags.equals(that.removedTags)) + && (Objects.equals(this.customTag, that.customTag)) @@ -1678,7 +1708,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - && (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood()) - && (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool()) - && (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable()) -- && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) -+ && (Objects.equals(this.damage, that.damage)) // Paper - preserve empty/0 damage - && (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage()) - && (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper - && (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper + && (this.hasFood() ? that.hasFood() && this.food.equals(that.food) : !that.hasFood()) + && (this.hasTool() ? that.hasTool() && this.tool.equals(that.tool) : !that.hasTool()) + && (this.hasJukeboxPlayable() ? that.hasJukeboxPlayable() && this.jukebox.equals(that.jukebox) : !that.hasJukeboxPlayable()) +- && (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage()) ++ && (Objects.equals(this.damage, that.damage)) // Paper - preserve empty/0 damage + && (this.hasMaxDamage() ? that.hasMaxDamage() && this.maxDamage.equals(that.maxDamage) : !that.hasMaxDamage()) + && (this.canPlaceOnPredicates != null ? that.canPlaceOnPredicates != null && this.canPlaceOnPredicates.equals(that.canPlaceOnPredicates) : that.canPlaceOnPredicates == null) // Paper + && (this.canBreakPredicates != null ? that.canBreakPredicates != null && this.canBreakPredicates.equals(that.canBreakPredicates) : that.canBreakPredicates == null) // Paper @@ -1724,9 +1754,9 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0); - hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0); - hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0); -- hash = 61 * hash + (this.hasDamage() ? this.damage : 0); -- hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237); -- hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); -+ hash = 61 * hash + (this.hasDamageValue() ? this.damage : -1); // Paper - preserve empty/0 damage -+ hash = 61 * hash + (this.hasMaxDamage() ? this.maxDamage.hashCode() : 0); // Paper - max damage is not a boolean -+ hash = 61 * hash + (this.attributeModifiers != null ? this.attributeModifiers.hashCode() : 0); // Paper - track only null attributes - hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper - hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper - hash = 61 * hash + this.version; + hash = 61 * hash + (this.hasFood() ? this.food.hashCode() : 0); + hash = 61 * hash + (this.hasTool() ? this.tool.hashCode() : 0); + hash = 61 * hash + (this.hasJukeboxPlayable() ? this.jukebox.hashCode() : 0); +- hash = 61 * hash + (this.hasDamage() ? this.damage : 0); +- hash = 61 * hash + (this.hasMaxDamage() ? 1231 : 1237); +- hash = 61 * hash + (this.hasAttributeModifiers() ? this.attributeModifiers.hashCode() : 0); ++ hash = 61 * hash + (this.hasDamageValue() ? this.damage : -1); // Paper - preserve empty/0 damage ++ hash = 61 * hash + (this.hasMaxDamage() ? this.maxDamage.hashCode() : 0); // Paper - max damage is not a boolean ++ hash = 61 * hash + (this.attributeModifiers != null ? this.attributeModifiers.hashCode() : 0); // Paper - track only null attributes + hash = 61 * hash + (this.canPlaceOnPredicates != null ? this.canPlaceOnPredicates.hashCode() : 0); // Paper + hash = 61 * hash + (this.canBreakPredicates != null ? this.canBreakPredicates.hashCode() : 0); // Paper + hash = 61 * hash + this.version; @@ -1746,7 +1776,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (this.enchantments != null) { - clone.enchantments = new EnchantmentMap(this.enchantments); // Paper - } -- if (this.hasAttributeModifiers()) { -+ if (this.attributeModifiers != null) { // Paper - clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); - } - if (this.customTag != null) { -@@ -1874,7 +1904,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - builder.put(CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, this.jukebox); + if (this.enchantments != null) { + clone.enchantments = new EnchantmentMap(this.enchantments); // Paper } - -- if (this.hasDamage()) { -+ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage - builder.put(CraftMetaItem.DAMAGE.BUKKIT, this.damage); +- if (this.hasAttributeModifiers()) { ++ if (this.attributeModifiers != null) { // Paper + clone.attributeModifiers = LinkedHashMultimap.create(this.attributeModifiers); } + if (this.customTag != null) { +@@ -1874,7 +1904,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + builder.put(CraftMetaItem.JUKEBOX_PLAYABLE.BUKKIT, this.jukebox); + } -@@ -1975,7 +2005,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { +- if (this.hasDamage()) { ++ if (this.hasDamageValue()) { // Paper - preserve empty/0 damage + builder.put(CraftMetaItem.DAMAGE.BUKKIT, this.damage); } - static void serializeModifiers(Multimap modifiers, ImmutableMap.Builder builder, ItemMetaKey key) { -- if (modifiers == null || modifiers.isEmpty()) { -+ if (modifiers == null/* || modifiers.isEmpty()*/) { // Paper - null and an empty map have different behaviors - return; - } +@@ -1975,7 +2005,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + } + + static void serializeModifiers(Multimap modifiers, ImmutableMap.Builder builder, ItemMetaKey key) { +- if (modifiers == null || modifiers.isEmpty()) { ++ if (modifiers == null/* || modifiers.isEmpty()*/) { // Paper - null and an empty map have different behaviors + return; + } @@ -2057,7 +2087,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - // Paper start - improve checking handled tags - @org.jetbrains.annotations.VisibleForTesting - public static final Map, Set>> HANDLED_DCTS_PER_TYPE = new HashMap<>(); -- private static final Set> DEFAULT_HANDLED_DCTS = Set.of( -+ protected static final Set> DEFAULT_HANDLED_DCTS = Set.of( - CraftMetaItem.NAME.TYPE, - CraftMetaItem.ITEM_NAME.TYPE, - CraftMetaItem.LORE.TYPE, -@@ -2126,6 +2156,12 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + // Paper start - improve checking handled tags + @org.jetbrains.annotations.VisibleForTesting + public static final Map, Set>> HANDLED_DCTS_PER_TYPE = new HashMap<>(); +- private static final Set> DEFAULT_HANDLED_DCTS = Set.of( ++ protected static final Set> DEFAULT_HANDLED_DCTS = Set.of( + CraftMetaItem.NAME.TYPE, + CraftMetaItem.ITEM_NAME.TYPE, + CraftMetaItem.LORE.TYPE, +@@ -2125,7 +2155,12 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { + // Paper end - improve checking handled data component types protected static Optional getOrEmpty(DataComponentPatch tag, ItemMetaKeyType type) { - Optional result = tag.get(type.TYPE); +- Optional result = tag.get(type.TYPE); + // Paper start + return getOrEmpty(tag, type.TYPE); + } diff --git a/patches/server/0977-Fix-equipment-slot-and-group-API.patch b/patches/server/0977-Fix-equipment-slot-and-group-API.patch index 5c9b90b127fb..12c1d026ea6f 100644 --- a/patches/server/0977-Fix-equipment-slot-and-group-API.patch +++ b/patches/server/0977-Fix-equipment-slot-and-group-API.patch @@ -52,29 +52,29 @@ index 9d74577af071954e1e37201a96368c1360076209..eafa54c870c3e2aef30c3f9f96f51660 throw new IllegalArgumentException("Not implemented. This is a bug"); } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java -index a82b8e123d3df343f643bdcf007bc3632518c6a1..cc9de0a940deb21c1ed660567e7d419fedcfd376 100644 +index 776f4dcc0b61a5b8ee4020a283cfcfacefbe682e..9aef0223cd790d9f4a74dfe22e7926027c08dca5 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -1452,7 +1452,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components - SetMultimap result = LinkedHashMultimap.create(); - for (Map.Entry entry : this.attributeModifiers.entries()) { -- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components + SetMultimap result = LinkedHashMultimap.create(); + for (Map.Entry entry : this.attributeModifiers.entries()) { +- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group - result.put(entry.getKey(), entry.getValue()); - } + result.put(entry.getKey(), entry.getValue()); } + } @@ -1520,9 +1520,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { - while (iter.hasNext()) { - Map.Entry entry = iter.next(); -- // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a - -- // set slot are active in any slot. -- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + while (iter.hasNext()) { + Map.Entry entry = iter.next(); +- // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a - +- // set slot are active in any slot. +- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) { + if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group - iter.remove(); - ++removed; - } + iter.remove(); + ++removed; + } diff --git a/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java b/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ee0bfe4edb134d7ea3a3b97f5102a7f3122c3b99 From 9916c7a8d2372746b5343b61a77d138d90d39418 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sat, 6 Jul 2024 18:12:11 +0200 Subject: [PATCH 3/5] MM feedback --- .../0289-Mob-Spawner-API-Enhancements.patch | 4 ++-- ...prove-fix-EntityTargetLivingEntityEvent.patch | 16 ++-------------- ...0544-Improve-item-default-attribute-API.patch | 2 -- ...illa-handling-of-LivingEntity-actuallyH.patch | 11 +---------- 4 files changed, 5 insertions(+), 28 deletions(-) diff --git a/patches/server/0289-Mob-Spawner-API-Enhancements.patch b/patches/server/0289-Mob-Spawner-API-Enhancements.patch index 1f15425c9cac..d13a80053ed3 100644 --- a/patches/server/0289-Mob-Spawner-API-Enhancements.patch +++ b/patches/server/0289-Mob-Spawner-API-Enhancements.patch @@ -121,7 +121,7 @@ index 9b2b6697d0b64da2bc99dc646f552c2689d5a1fc..146dde200845abcbe11015dda2c826a1 + // Paper end - more spawner API } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java -index 72e34dbfadcebb26a0707ce095b0d270f4d1d97c..66cf668183cfdb36f567729a40d01d996ed507e1 100644 +index 72e34dbfadcebb26a0707ce095b0d270f4d1d97c..e8ece01669373ecf6552d33b2ed72668524e2650 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMinecartMobSpawner.java @@ -16,7 +16,7 @@ import org.bukkit.entity.EntitySnapshot; @@ -129,7 +129,7 @@ index 72e34dbfadcebb26a0707ce095b0d270f4d1d97c..66cf668183cfdb36f567729a40d01d99 import org.bukkit.entity.minecart.SpawnerMinecart; -final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMinecart { -+final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMinecart, org.bukkit.craftbukkit.spawner.PaperSharedSpawnerLogic { ++final class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMinecart, org.bukkit.craftbukkit.spawner.PaperSharedSpawnerLogic { // Paper - more spawner API CraftMinecartMobSpawner(CraftServer server, MinecartSpawner entity) { super(server, entity); } diff --git a/patches/server/0383-Improve-fix-EntityTargetLivingEntityEvent.patch b/patches/server/0383-Improve-fix-EntityTargetLivingEntityEvent.patch index e6532342d152..29703174a113 100644 --- a/patches/server/0383-Improve-fix-EntityTargetLivingEntityEvent.patch +++ b/patches/server/0383-Improve-fix-EntityTargetLivingEntityEvent.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Improve/fix EntityTargetLivingEntityEvent diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java b/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java -index cc7d161b53a2295fa1745254eafb8a70c7b6c7b2..c4bd46435bef33bb743ef43a19edc0ad6854e256 100644 +index cc7d161b53a2295fa1745254eafb8a70c7b6c7b2..508d4f391fe563453d7bf6782b3082741c358006 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/StopAttackingIfTargetInvalid.java -@@ -47,16 +47,30 @@ public class StopAttackingIfTargetInvalid { +@@ -47,9 +47,22 @@ public class StopAttackingIfTargetInvalid { if (entityinsentient.canAttack(entityliving) && (!shouldForgetIfTargetUnreachable || !StopAttackingIfTargetInvalid.isTiredOfTryingToReachTarget(entityinsentient, behaviorbuilder_b.tryGet(memoryaccessor1))) && entityliving.isAlive() && entityliving.level() == entityinsentient.level() && !alternativeCondition.test(entityliving)) { return true; } else { @@ -33,15 +33,3 @@ index cc7d161b53a2295fa1745254eafb8a70c7b6c7b2..c4bd46435bef33bb743ef43a19edc0ad if (event.isCancelled()) { return false; } -- if (event.getTarget() != null) { -- entityinsentient.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); -- return true; -- } -+ // if (event.getTarget() == null) { // Paper - this is wrong, you are skipping the forgetCallback -+ // entityinsentient.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); -+ // return true; -+ // } -+ // entityliving = ((CraftLivingEntity) event.getTarget()).getHandle(); - // CraftBukkit end - forgetCallback.accept(entityinsentient, entityliving); - memoryaccessor.erase(); diff --git a/patches/server/0544-Improve-item-default-attribute-API.patch b/patches/server/0544-Improve-item-default-attribute-API.patch index d53f1f5c0370..5a9d7ca28070 100644 --- a/patches/server/0544-Improve-item-default-attribute-API.patch +++ b/patches/server/0544-Improve-item-default-attribute-API.patch @@ -3,8 +3,6 @@ From: Jake Potrebic Date: Sat, 8 May 2021 15:01:54 -0700 Subject: [PATCH] Improve item default attribute API -Also fixes an issue where upstream isn't -actually getting the correct default attributes diff --git a/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java b/src/main/java/org/bukkit/craftbukkit/attribute/CraftAttributeInstance.java index de0eba19c0c963adb4f17cea22333240021fd801..3b171a08bd0bedfe224905feb5838d2540199bce 100644 diff --git a/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch b/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch index c6c2190fe5bb..3d5ca78e1631 100644 --- a/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch +++ b/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch @@ -5,18 +5,9 @@ Subject: [PATCH] Revert to vanilla handling of LivingEntity#actuallyHurt diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 8072d31525d9c7890804bb879893f1a69820e32d..de2b1f8e1c9883babe4ded372d51de616d9b44ca 100644 +index 8072d31525d9c7890804bb879893f1a69820e32d..abed03b44a2b0beb9931e52be9a5ce57001ae579 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2301,7 +2301,7 @@ public abstract class LivingEntity extends Entity implements Attackable { - return CraftEventFactory.handleLivingEntityDamageEvent(this, damagesource, originalDamage, freezingModifier, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, freezing, hardHat, blocking, armor, resistance, magic, absorption); - } - -- protected boolean actuallyHurt(final DamageSource damagesource, float f, final EntityDamageEvent event) { // void -> boolean, add final -+ protected boolean actuallyHurt(final DamageSource damagesource, float f, final EntityDamageEvent event) { // void -> boolean, add final // Paper - return false ONLY if event cancelled - if (!this.isInvulnerableTo(damagesource)) { - if (event.isCancelled()) { - return false; @@ -2411,12 +2411,12 @@ public abstract class LivingEntity extends Entity implements Attackable { return true; From 41cd7cd1fb901b819b7f4902cac74377c362ba99 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sat, 6 Jul 2024 19:05:57 +0200 Subject: [PATCH 4/5] Lulu comments --- .../server/0289-Mob-Spawner-API-Enhancements.patch | 7 ++++--- .../0918-Restore-vanilla-entity-drops-behavior.patch | 12 +++++------- patches/server/0924-Add-drops-to-shear-events.patch | 8 ++++---- patches/server/1009-Optimize-Hoppers.patch | 10 +++++----- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/patches/server/0289-Mob-Spawner-API-Enhancements.patch b/patches/server/0289-Mob-Spawner-API-Enhancements.patch index d13a80053ed3..9f35b91c5a99 100644 --- a/patches/server/0289-Mob-Spawner-API-Enhancements.patch +++ b/patches/server/0289-Mob-Spawner-API-Enhancements.patch @@ -157,10 +157,10 @@ index 72e34dbfadcebb26a0707ce095b0d270f4d1d97c..e8ece01669373ecf6552d33b2ed72668 } diff --git a/src/main/java/org/bukkit/craftbukkit/spawner/PaperSharedSpawnerLogic.java b/src/main/java/org/bukkit/craftbukkit/spawner/PaperSharedSpawnerLogic.java new file mode 100644 -index 0000000000000000000000000000000000000000..e01bf4afb04ae66dee8c194743709aa6ac0e4633 +index 0000000000000000000000000000000000000000..b1d08dc4c4257a6f5cd70dfdddade58ff7eedb4b --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/spawner/PaperSharedSpawnerLogic.java -@@ -0,0 +1,55 @@ +@@ -0,0 +1,56 @@ +package org.bukkit.craftbukkit.spawner; + +import com.google.common.base.Preconditions; @@ -168,6 +168,7 @@ index 0000000000000000000000000000000000000000..e01bf4afb04ae66dee8c194743709aa6 +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.nbt.CompoundTag; ++import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.BaseSpawner; +import net.minecraft.world.level.Level; @@ -204,7 +205,7 @@ index 0000000000000000000000000000000000000000..e01bf4afb04ae66dee8c194743709aa6 + + final net.minecraft.world.item.ItemStack item = CraftItemStack.asNMSCopy(itemStack); + final CompoundTag entity = new CompoundTag(); -+ entity.putString("id", BuiltInRegistries.ENTITY_TYPE.getKey(EntityType.ITEM).toString()); ++ entity.putString(Entity.ID_TAG, BuiltInRegistries.ENTITY_TYPE.getKey(EntityType.ITEM).toString()); + entity.put("Item", item.save(this.getInternalWorld().registryAccess())); + + this.setNextSpawnData( diff --git a/patches/server/0918-Restore-vanilla-entity-drops-behavior.patch b/patches/server/0918-Restore-vanilla-entity-drops-behavior.patch index f0dcb68052c2..7aa60b4674b2 100644 --- a/patches/server/0918-Restore-vanilla-entity-drops-behavior.patch +++ b/patches/server/0918-Restore-vanilla-entity-drops-behavior.patch @@ -9,10 +9,10 @@ on dropping the item instead of generalizing it for all dropped items like CB does. diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index f568fa18ddcb1a1cd060c469edd6db45431bb53c..09e60ea5c25f23bcc7e24f16c7a31f616d249ff9 100644 +index f568fa18ddcb1a1cd060c469edd6db45431bb53c..191dfbd0f15c3a21278f3c4f9ce29f1698e0836c 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -978,22 +978,20 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { +@@ -978,20 +978,20 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player { if (this.isRemoved()) { return; } @@ -32,12 +32,10 @@ index f568fa18ddcb1a1cd060c469edd6db45431bb53c..09e60ea5c25f23bcc7e24f16c7a31f61 // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule) this.dropFromLootTable(damageSource, this.lastHurtByPlayerTime > 0); - this.dropCustomDeathLoot(this.serverLevel(), damageSource, flag); -- -- loot.addAll(this.drops); -+ loot.addAll(this.drops); // Paper - this.drops.clear(); // SPIGOT-5188: make sure to clear - } // Paper - fix player loottables running when mob loot gamerule is false ++ // Paper - Restore vanilla drops behaviour; custom death loot is a noop on server player, remove. + loot.addAll(this.drops); + this.drops.clear(); // SPIGOT-5188: make sure to clear diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 24aacf9997c9ea0bd68ef3803f4a3ee4a920ab44..363fe1aff439983199f5137547cef9516fbab2a8 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java diff --git a/patches/server/0924-Add-drops-to-shear-events.patch b/patches/server/0924-Add-drops-to-shear-events.patch index e50accc3111c..9a344bf8ac10 100644 --- a/patches/server/0924-Add-drops-to-shear-events.patch +++ b/patches/server/0924-Add-drops-to-shear-events.patch @@ -233,7 +233,7 @@ index 2de1a2f666da9db1832907e1651dbff948e37252..5c2ed3c39c8eb850f3be1e2ea5b5a7ea } diff --git a/src/main/java/net/minecraft/world/entity/monster/Bogged.java b/src/main/java/net/minecraft/world/entity/monster/Bogged.java -index dc6230458e09f7555eee7f6a567ff60ad454666b..601a1460e92754b05b337d3f53f84ac2d85f09c8 100644 +index dc6230458e09f7555eee7f6a567ff60ad454666b..9d50b9ac8084f3db1844cc7ad1ce9153614ff9d9 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Bogged.java +++ b/src/main/java/net/minecraft/world/entity/monster/Bogged.java @@ -80,12 +80,19 @@ public class Bogged extends AbstractSkeleton implements Shearable { @@ -248,7 +248,7 @@ index dc6230458e09f7555eee7f6a567ff60ad454666b..601a1460e92754b05b337d3f53f84ac2 + final org.bukkit.event.player.PlayerShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.handlePlayerShearEntityEvent(player, this, itemstack, hand, drops); + if (event != null) { + if (event.isCancelled()) { -+ this.getEntityData().markDirty(Bogged.DATA_SHEARED); // CraftBukkit - mark dirty to restore sheared state to clients ++ if (player instanceof final net.minecraft.server.level.ServerPlayer serverPlayer) this.resendPossiblyDesyncedDataValues(java.util.List.of(Bogged.DATA_SHEARED), serverPlayer); + return InteractionResult.PASS; + } + drops = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getDrops()); @@ -278,7 +278,7 @@ index dc6230458e09f7555eee7f6a567ff60ad454666b..601a1460e92754b05b337d3f53f84ac2 } private void spawnShearedMushrooms() { -+ // Paper start - shear drops API ++ // Paper start - shear drops API + this.spawnDrops(generateDefaultDrops()); // Only here for people calling spawnSheardMushrooms. Not used otherwise. + } + private void spawnDrops(java.util.List drops) { @@ -289,7 +289,7 @@ index dc6230458e09f7555eee7f6a567ff60ad454666b..601a1460e92754b05b337d3f53f84ac2 + }); + } + private void generateShearedMushrooms(java.util.function.Consumer stackConsumer) { -+ // Paper end - shear drops API ++ // Paper end - shear drops API Level world = this.level(); if (world instanceof ServerLevel worldserver) { diff --git a/patches/server/1009-Optimize-Hoppers.patch b/patches/server/1009-Optimize-Hoppers.patch index 3eaae2401748..7ac3c6b82337 100644 --- a/patches/server/1009-Optimize-Hoppers.patch +++ b/patches/server/1009-Optimize-Hoppers.patch @@ -105,7 +105,7 @@ index cd3b952a228c09077c2e74183a34ddb32811280b..c0563260277f9f4bd9ff08993b2efb4b } diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java -index 0d6132abd49d66fbf84c046e09144cb33651be15..b3cd4bf8e4d7718e8d98ef5e085621ecc85d93a9 100644 +index 0d6132abd49d66fbf84c046e09144cb33651be15..53f9d28bf3c6aafd4fdd6c12e0285500fe7350ce 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java @@ -156,6 +156,43 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen @@ -440,7 +440,7 @@ index 0d6132abd49d66fbf84c046e09144cb33651be15..b3cd4bf8e4d7718e8d98ef5e085621ec + // InventoryMoveItemEvent event = new InventoryMoveItemEvent(tileentityhopper.getOwner().getInventory(), oitemstack, destinationInventory, true); + // world.getCraftServer().getPluginManager().callEvent(event); + // if (event.isCancelled()) { -+ // blockEntity.setItem(i, itemstack); ++ // blockEntity.setItem(i, original); + // blockEntity.setCooldown(world.spigotConfig.hopperTransfer); // Delay hopper checks // Spigot + // return false; + // } @@ -454,7 +454,7 @@ index 0d6132abd49d66fbf84c046e09144cb33651be15..b3cd4bf8e4d7718e8d98ef5e085621ec + + // itemstack.setCount(j); + // if (j == 1) { -+ // blockEntity.setItem(i, original); ++ // blockEntity.setItem(i, itemstack); + // } + // } + //} @@ -544,7 +544,7 @@ index 0d6132abd49d66fbf84c046e09144cb33651be15..b3cd4bf8e4d7718e8d98ef5e085621ec + + // Bukkit.getServer().getPluginManager().callEvent(event); + // if (event.isCancelled()) { -+ // iinventory.setItem(i, itemstack); ++ // iinventory.setItem(i, original); + + // if (ihopper instanceof HopperBlockEntity) { + // ((HopperBlockEntity) ihopper).setCooldown(world.spigotConfig.hopperTransfer); // Spigot @@ -562,7 +562,7 @@ index 0d6132abd49d66fbf84c046e09144cb33651be15..b3cd4bf8e4d7718e8d98ef5e085621ec + + // itemstack.setCount(j); + // if (j == 1) { -+ // iinventory.setItem(i, original); ++ // iinventory.setItem(i, itemstack); + // } + // Paper end - Perf: Optimize Hoppers } From fafdb2633f7287de6d693b40f7dad718aff1f247 Mon Sep 17 00:00:00 2001 From: Bjarne Koll Date: Sat, 6 Jul 2024 21:12:44 +0200 Subject: [PATCH 5/5] Do not process 0F damage for players Mirrors Player#hurt checks before calling super#hurt. --- ...a-handling-of-LivingEntity-actuallyH.patch | 25 +++++++++++++++++-- ...oversized-item-data-in-equipment-and.patch | 4 +-- ...amage-tick-when-blocking-with-shield.patch | 4 +-- ...cing-for-EntityLiving-hasLineOfSight.patch | 4 +-- ...9-Improve-boat-collision-performance.patch | 6 ++--- .../1023-Properly-resend-entities.patch | 4 +-- 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch b/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch index 3d5ca78e1631..80a48db778d9 100644 --- a/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch +++ b/patches/server/0968-Revert-to-vanilla-handling-of-LivingEntity-actuallyH.patch @@ -5,10 +5,31 @@ Subject: [PATCH] Revert to vanilla handling of LivingEntity#actuallyHurt diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 8072d31525d9c7890804bb879893f1a69820e32d..abed03b44a2b0beb9931e52be9a5ce57001ae579 100644 +index 8072d31525d9c7890804bb879893f1a69820e32d..d41e22ff113231923d95567244fd33dcc4f320d4 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2411,12 +2411,12 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1476,9 +1476,11 @@ public abstract class LivingEntity extends Entity implements Attackable { + } + + // CraftBukkit start +- if (!this.actuallyHurt(source, (float) event.getFinalDamage() - this.lastHurt, event)) { ++ final float actualDamage = (float) event.getFinalDamage() - this.lastHurt; // Paper - revert to vanilla damage - move out for diff on change ++ if (!this.actuallyHurt(source, actualDamage, event)) { // Paper - revert to vanilla damage - move out for diff on change + return false; + } ++ if (this instanceof ServerPlayer && actualDamage == 0.0F) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0. + // CraftBukkit end + this.lastHurt = amount; + flag1 = false; +@@ -1487,6 +1489,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + if (!this.actuallyHurt(source, (float) event.getFinalDamage(), event)) { + return false; + } ++ if (this instanceof ServerPlayer && event.getFinalDamage() == 0.0F) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0. + this.lastHurt = amount; + this.invulnerableTime = this.invulnerableDuration; // CraftBukkit - restore use of maxNoDamageTicks + // this.actuallyHurt(damagesource, f); +@@ -2411,12 +2414,12 @@ public abstract class LivingEntity extends Entity implements Attackable { return true; } else { diff --git a/patches/server/0979-Prevent-sending-oversized-item-data-in-equipment-and.patch b/patches/server/0979-Prevent-sending-oversized-item-data-in-equipment-and.patch index 5ba0aae52edd..bc65ef627cec 100644 --- a/patches/server/0979-Prevent-sending-oversized-item-data-in-equipment-and.patch +++ b/patches/server/0979-Prevent-sending-oversized-item-data-in-equipment-and.patch @@ -214,10 +214,10 @@ index 60c65af218d533d53b765ba2175fed163c32c126..a0f5839719ca0ce6ed048229f074041b } } diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index de2b1f8e1c9883babe4ded372d51de616d9b44ca..9a0d4120d4735c2d8057bc55d2599bc38d5b4714 100644 +index d41e22ff113231923d95567244fd33dcc4f320d4..ea983f83bb8d511e5a978cd4168888b705f94bbb 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3351,7 +3351,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3354,7 +3354,7 @@ public abstract class LivingEntity extends Entity implements Attackable { } }); diff --git a/patches/server/0989-Configurable-damage-tick-when-blocking-with-shield.patch b/patches/server/0989-Configurable-damage-tick-when-blocking-with-shield.patch index c309af0ddb75..37ff30938d26 100644 --- a/patches/server/0989-Configurable-damage-tick-when-blocking-with-shield.patch +++ b/patches/server/0989-Configurable-damage-tick-when-blocking-with-shield.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Configurable damage tick when blocking with shield diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 9a0d4120d4735c2d8057bc55d2599bc38d5b4714..2812269f11169a9e5c7ce5c3e86a2ead0268c7c9 100644 +index ea983f83bb8d511e5a978cd4168888b705f94bbb..70f42996f722edc0435a75d22985940ffba9b409 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -2409,7 +2409,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2412,7 +2412,7 @@ public abstract class LivingEntity extends Entity implements Attackable { CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, originalDamage, f, true); // Paper - fix taken/dealt param order } diff --git a/patches/server/0996-Strip-raytracing-for-EntityLiving-hasLineOfSight.patch b/patches/server/0996-Strip-raytracing-for-EntityLiving-hasLineOfSight.patch index 101484351a01..1b46f688d115 100644 --- a/patches/server/0996-Strip-raytracing-for-EntityLiving-hasLineOfSight.patch +++ b/patches/server/0996-Strip-raytracing-for-EntityLiving-hasLineOfSight.patch @@ -26,10 +26,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 2812269f11169a9e5c7ce5c3e86a2ead0268c7c9..f53e6ac5ac1ac0ca0d9095c812a2e60a165d36dd 100644 +index 70f42996f722edc0435a75d22985940ffba9b409..eedbf5e73dcf4019f408a9098e020488d32ccf4c 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3772,7 +3772,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3775,7 +3775,7 @@ public abstract class LivingEntity extends Entity implements Attackable { Vec3 vec3d1 = new Vec3(entity.getX(), entity.getEyeY(), entity.getZ()); // Paper - diff on change - used in CraftLivingEntity#hasLineOfSight(Location) and CraftWorld#lineOfSightExists diff --git a/patches/server/1019-Improve-boat-collision-performance.patch b/patches/server/1019-Improve-boat-collision-performance.patch index 4be9644f8768..f1ba576e9016 100644 --- a/patches/server/1019-Improve-boat-collision-performance.patch +++ b/patches/server/1019-Improve-boat-collision-performance.patch @@ -17,7 +17,7 @@ index 42d7ecfab6f72517904451d9df3f0404b176fdb2..5869f2f5c72f736e6b077683327c64b9 }; diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index f53e6ac5ac1ac0ca0d9095c812a2e60a165d36dd..b9d107a86bbb9ace55fec9477f052ae3c1bd4e35 100644 +index eedbf5e73dcf4019f408a9098e020488d32ccf4c..ba4d69415a68442a93026c3ca9213f0fa44ca62e 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java @@ -1437,7 +1437,7 @@ public abstract class LivingEntity extends Entity implements Attackable { @@ -29,7 +29,7 @@ index f53e6ac5ac1ac0ca0d9095c812a2e60a165d36dd..b9d107a86bbb9ace55fec9477f052ae3 LivingEntity entityliving = (LivingEntity) entity; this.blockUsingShield(entityliving); -@@ -1544,8 +1544,13 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -1547,8 +1547,13 @@ public abstract class LivingEntity extends Entity implements Attackable { double d0 = 0.0D; double d1 = 0.0D; Entity entity2 = source.getDirectEntity(); @@ -45,7 +45,7 @@ index f53e6ac5ac1ac0ca0d9095c812a2e60a165d36dd..b9d107a86bbb9ace55fec9477f052ae3 Projectile iprojectile = (Projectile) entity2; DoubleDoubleImmutablePair doubledoubleimmutablepair = iprojectile.calculateHorizontalHurtKnockbackDirection(this, source); -@@ -2349,7 +2354,7 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -2352,7 +2357,7 @@ public abstract class LivingEntity extends Entity implements Attackable { this.hurtCurrentlyUsedShield((float) -event.getDamage(DamageModifier.BLOCKING)); Entity entity = damagesource.getDirectEntity(); diff --git a/patches/server/1023-Properly-resend-entities.patch b/patches/server/1023-Properly-resend-entities.patch index 7b7e3cc85fdd..b1cbc31142f6 100644 --- a/patches/server/1023-Properly-resend-entities.patch +++ b/patches/server/1023-Properly-resend-entities.patch @@ -166,10 +166,10 @@ index f1fb4e830c6720d09b22056e3d0b9a08fe2bd472..83f3ffdd8fa901b3de580d2359cdb5ea public boolean equals(Object object) { return object instanceof Entity ? ((Entity) object).id == this.id : false; diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index b9d107a86bbb9ace55fec9477f052ae3c1bd4e35..542dff99accb726e70bf2a245925991c5509e0d8 100644 +index ba4d69415a68442a93026c3ca9213f0fa44ca62e..c4b10ce2fd9f1e346aa9240e354b0583b90d2bdc 100644 --- a/src/main/java/net/minecraft/world/entity/LivingEntity.java +++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -3874,6 +3874,11 @@ public abstract class LivingEntity extends Entity implements Attackable { +@@ -3877,6 +3877,11 @@ public abstract class LivingEntity extends Entity implements Attackable { return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; }